Class InMemoryKeyStore
In-memory IKeyStore test double. Generates a random 256-bit data-encryption key
(DEK) per KeyScope on first use, hands the embedded key id back on lookup, and
supports rotation, revocation, and scope erasure with the same observable semantics as the
production EnvelopeFileKeyStore — but without KEK wrapping, on-disk files, or a
IMasterKeyProvider.
public sealed class InMemoryKeyStore : IKeyStore
- Inheritance
-
InMemoryKeyStore
- Implements
- Inherited Members
- Extension Methods
Remarks
Use it wherever production code depends on IKeyStore (blob encryption, field encryption, crypto-shredding tests). Pair it with CreateAesGcm() to round-trip blobs through the real AES-GCM encryptor. Every returned key buffer is a fresh copy, so callers that zero their copy after use (as the production encryptor does) do not corrupt the stored material. All members are thread-safe.
Methods
EraseScopeAsync(KeyScope, CancellationToken)
Erase every key version for the scope (GDPR Art. 17). All ciphertext under the scope becomes permanently undecryptable.
public ValueTask EraseScopeAsync(KeyScope scope, CancellationToken cancellationToken = default)
Parameters
scopeKeyScopeThe key scope to erase.
cancellationTokenCancellationTokenPropagated to the underlying store.
Returns
GetDataEncryptionKeyAsync(string, CancellationToken)
Return the raw key bytes for the id, or null if revoked / erased / unknown.
public ValueTask<byte[]?> GetDataEncryptionKeyAsync(string keyId, CancellationToken cancellationToken = default)
Parameters
keyIdstringThe key id previously obtained from GetOrCreateCurrentKeyAsync(KeyScope, CancellationToken).
cancellationTokenCancellationTokenPropagated to the underlying store.
Returns
GetOrCreateCurrentKeyAsync(KeyScope, CancellationToken)
Return the current (highest non-revoked version) key for the scope, creating a first version if none exists yet.
public ValueTask<KeyMaterial> GetOrCreateCurrentKeyAsync(KeyScope scope, CancellationToken cancellationToken = default)
Parameters
scopeKeyScopeThe key scope to resolve.
cancellationTokenCancellationTokenPropagated to the underlying store.
Returns
- ValueTask<KeyMaterial>
The resolved KeyMaterial (key id + raw bytes).
RevokeAsync(string, CancellationToken)
Permanently revoke a single key version. After revocation GetDataEncryptionKeyAsync(string, CancellationToken) returns null for that id — the ciphertext encrypted under it becomes undecryptable (crypto-shred of one version).
public ValueTask RevokeAsync(string keyId, CancellationToken cancellationToken = default)
Parameters
keyIdstringThe key id to revoke.
cancellationTokenCancellationTokenPropagated to the underlying store.
Returns
RotateAsync(KeyScope, CancellationToken)
Create a new key version for the scope and make it the current one. Older versions remain resolvable via GetDataEncryptionKeyAsync(string, CancellationToken) so existing ciphertext stays readable.
public ValueTask<string> RotateAsync(KeyScope scope, CancellationToken cancellationToken = default)
Parameters
scopeKeyScopeThe key scope to rotate.
cancellationTokenCancellationTokenPropagated to the underlying store.