AwsEncryptionSdk.Cmm.Caching (AWS Encryption SDK v1.0.0)
View SourceCaching Cryptographic Materials Manager implementation.
The Caching CMM wraps another CMM and caches cryptographic materials to reduce expensive calls to key providers. It provides:
- Performance: Caches generated data keys and EDKs
- Security: Enforces key rotation via TTL and usage limits
- Sharing: Multiple Caching CMMs can share cache via Partition IDs
Example
# Create cache
{:ok, cache} = LocalCache.start_link([])
# Create caching CMM with keyring
{:ok, keyring} = RawAes.new("ns", "key", key_bytes, :aes_256_gcm)
cmm = Caching.new_with_keyring(keyring, cache, max_age: 300)
# Or wrap an existing CMM
default_cmm = Default.new(keyring)
cmm = Caching.new(default_cmm, cache, max_age: 300)Usage limits
Each cache entry tracks how many messages and plaintext bytes it has served.
An entry is refreshed (fresh materials fetched and cached) rather than
reused when serving the request would exceed max_messages or push the
entry's cumulative bytes past max_bytes, so no entry ever serves more
than max_bytes bytes. The one exception is a single request larger than
max_bytes on its own: it is served once with fresh materials by design,
and the entry is refreshed on the next request.
The byte limit is enforced against the request's :max_plaintext_length.
AwsEncryptionSdk.Client.encrypt/3 sets it automatically from the
plaintext size. Streaming callers must pass :plaintext_length to
AwsEncryptionSdk.Stream.encrypt/3 when they know the total size; when a
request carries no length, the byte limit cannot be enforced, so this CMM
bypasses the cache entirely for that request (the underlying CMM is called
and the result is not cached). Decryption is unaffected - usage limits are
encrypt-only per the spec.
Spec Reference
https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/caching-cmm.md
Summary
Functions
Creates a new Caching CMM wrapping an existing CMM.
Creates a new Caching CMM from a keyring.
Types
@type cache() :: AwsEncryptionSdk.Cache.LocalCache.t()
@type t() :: %AwsEncryptionSdk.Cmm.Caching{ cache: cache(), max_age: pos_integer(), max_bytes: non_neg_integer(), max_messages: non_neg_integer(), partition_id: binary(), underlying_cmm: AwsEncryptionSdk.Cmm.Behaviour.t() }
Functions
@spec new(AwsEncryptionSdk.Cmm.Behaviour.t(), cache(), keyword()) :: t()
Creates a new Caching CMM wrapping an existing CMM.
Parameters
underlying_cmm- The CMM to wrap (Default, RequiredEncryptionContext, etc.)cache- A CMC implementation (e.g., LocalCache pid)opts- Options::max_age- Required. TTL in seconds (must be > 0):partition_id- Optional. UUID for cache partitioning (auto-generated if omitted):max_bytes- Optional. Maximum bytes to encrypt per entry (default: 2^63-1):max_messages- Optional. Maximum messages per entry (default: 2^32)
Examples
iex> key = :crypto.strong_rand_bytes(32)
iex> {:ok, keyring} = AwsEncryptionSdk.Keyring.RawAes.new("ns", "key", key, :aes_256_gcm)
iex> default_cmm = AwsEncryptionSdk.Cmm.Default.new(keyring)
iex> {:ok, cache} = AwsEncryptionSdk.Cache.LocalCache.start_link([])
iex> cmm = AwsEncryptionSdk.Cmm.Caching.new(default_cmm, cache, max_age: 300)
iex> is_struct(cmm, AwsEncryptionSdk.Cmm.Caching)
true
@spec new_with_keyring(AwsEncryptionSdk.Cmm.Default.keyring(), cache(), keyword()) :: t()
Creates a new Caching CMM from a keyring.
The keyring is automatically wrapped in a Default CMM.
Parameters
keyring- A keyring structcache- A CMC implementationopts- Same asnew/3
Examples
iex> key = :crypto.strong_rand_bytes(32)
iex> {:ok, keyring} = AwsEncryptionSdk.Keyring.RawAes.new("ns", "key", key, :aes_256_gcm)
iex> {:ok, cache} = AwsEncryptionSdk.Cache.LocalCache.start_link([])
iex> cmm = AwsEncryptionSdk.Cmm.Caching.new_with_keyring(keyring, cache, max_age: 300)
iex> is_struct(cmm, AwsEncryptionSdk.Cmm.Caching)
true