Key Stores
Tayra uses a pluggable key store architecture to persist encryption keys. Every key store implements the IKeyStore interface, giving you freedom to choose the backend that best fits your infrastructure.
Available Providers
| Provider | Package | Use Case | Persistence | Encryption at Rest |
|---|---|---|---|---|
| In-Memory | Tayra.Core (built-in) | Unit tests, throwaway demos | No | No |
| SQLite | Tayra.KeyStore.Sqlite | Local development (zero-config) | Yes | No (raw key bytes) |
| PostgreSQL | Tayra.KeyStore.PostgreSql | Local dev or self-managed production | Yes | No (requires hardening) |
| HashiCorp Vault | Tayra.KeyStore.Vault | Production | Yes | Yes (seal) |
| Azure Key Vault | Tayra.KeyStore.AzureKeyVault | Production | Yes | Yes (HSM-backed) |
| AWS Parameter Store | Tayra.KeyStore.AwsParameterStore | Production | Yes | Yes (KMS) |
| AWS Secrets Manager | Tayra.KeyStore.AwsSecretsManager | Production (per-tenant) | Yes | Yes (KMS) |
| AWS Aurora (IAM auth) | Tayra.KeyStore.AwsAurora | Production (AWS-native PG) | Yes | No (requires hardening) |
Choosing a Key Store
| Environment | Recommended Provider | Why |
|---|---|---|
| Unit/integration tests | In-Memory | Zero configuration, no external dependencies |
| Local development | SQLite | Zero-config file-based persistence, no server needed |
| Local development (with PG) | PostgreSQL | Persistent keys, useful if you already run PostgreSQL locally |
| Self-managed production | PostgreSQL (with hardening) | For teams that don't use cloud secrets managers |
| Production on AWS Aurora | AWS Aurora (IAM auth) | PostgreSQL compatibility with ephemeral IAM DB auth tokens |
| Production | Vault, Azure Key Vault, or AWS KMS | HSM-backed encryption, access auditing, key wrapping |
SQLite - Development Only (in either role)
The SQLite key store stores raw key bytes without envelope encryption. It is for local development only - including when used as the master keystore via .WithSqliteMasterKey(...). Production deployments must use a hardened secrets manager regardless of role.
AWS Secrets Manager - Per-Secret Pricing
Secrets Manager bills $0.40 per secret per month. With Tayra's default per-data-subject key model, a customer base of 100k users costs ~$40k/month. Use AWS Parameter Store for per-subject keys; use Secrets Manager only for per-tenant key models or when policy mandates it.
PostgreSQL - Requires Hardening for Production
The PostgreSQL key store stores raw key bytes in a database table. It can be used in production only with proper hardening (TDE, TLS, pgAudit, least-privilege access). See the Production Security Guide for the full checklist. Without hardening, use it for development only.
The IKeyStore Interface
All key stores implement IKeyStore, which defines these operations:
public interface IKeyStore
{
Task StoreAsync(string keyId, byte[] key, CancellationToken ct = default);
Task<byte[]?> GetAsync(string keyId, CancellationToken ct = default);
Task DeleteAsync(string keyId, CancellationToken ct = default);
Task<bool> ExistsAsync(string keyId, CancellationToken ct = default);
Task DeleteByPrefixAsync(string prefix, CancellationToken ct = default);
Task<IReadOnlyList<string>> ListKeyIdsAsync(string prefix, CancellationToken ct = default);
Task<IReadOnlyList<KeyInfo>> GetKeysCreatedBeforeAsync(
DateTimeOffset cutoff, int limit = 100, CancellationToken ct = default);
}- StoreAsync - Stores a key. Implementations should be idempotent (no-op if the key already exists).
- GetAsync - Retrieves a key by ID. Returns
nullif the key has been deleted (crypto-shredded). - DeleteAsync - Deletes a key. This is the crypto-shredding operation.
- ExistsAsync - Checks whether a key exists without retrieving its value.
- DeleteByPrefixAsync - Bulk crypto-shredding by key prefix (e.g., delete all keys for a data subject).
- ListKeyIdsAsync - Lists key IDs matching a prefix. Used for key rotation discovery.
- GetKeysCreatedBeforeAsync - Finds keys older than a cutoff time. Used for data retention policies.
INFO
ListKeyIdsAsync and GetKeysCreatedBeforeAsync have default implementations that throw NotSupportedException. Not all providers support these operations.
Registration Pattern
Every key store follows the same chained registration pattern. Call services.AddTayra() to register core services and chain the provider-specific Use* method:
var services = new ServiceCollection();
services.AddTayra(opts => opts.LicenseKey = licenseKey);You can also build a custom key store if none of the built-in providers fit your needs.
See Also
- Installation - NuGet package installation for all providers
- Custom Key Store - Implementing your own
IKeyStore
