← Recipes

阅读中文版本

Envelope-Encrypt Data with a KMS

Generate a data key per object, encrypt data with it locally, and wrap the data key with a KMS master key so rotation does not require re-encrypting everything.

~45 minsecurityencryptionkms

Task

Encrypt stored objects with per-object data keys protected by a KMS master key.

When to use this

Encrypting everything directly with one master key makes rotation costly and puts the master key in more places than necessary.

Prerequisites

  • A KMS that supports generate-data-key and decrypt
  • A storage layer for ciphertext and wrapped keys

Steps

1. Ask the KMS for a data key and its wrapped form for each object.

Expected output: The plaintext data key exists only briefly in memory.

2. Encrypt the object locally with the data key and store the ciphertext plus the wrapped key.

Expected output: Only wrapped keys are persisted.

3. On read, ask the KMS to unwrap the data key and decrypt locally.

Expected output: The KMS is used for key operations, not bulk data.

4. Rotate the master key without re-encrypting data; rewrap keys on access.

aws kms generate-data-key --key-id alias/app --key-spec AES_256

Expected output: Rotation is cheap and incremental.

Troubleshooting

Problem

Plaintext data key logged

Solution

Never log or persist the plaintext data key; zero it after use.

Problem

KMS throttling

Solution

Cache unwrapped keys briefly and batch; KMS calls are limited and can become a bottleneck.

Limitations

  • Envelope encryption depends on KMS availability; an outage can block decryption unless keys are cached.
  • It protects data at rest and wrapped keys, not the application memory where plaintext exists during processing.

Context

Encrypt stored objects with per-object data keys protected by a KMS master key. Encrypting everything directly with one master key makes rotation costly and puts the master key in more places than necessary.

Steps

  1. Ask the KMS for a data key and its wrapped form for each object. Expected: The plaintext data key exists only briefly in memory.
  2. Encrypt the object locally with the data key and store the ciphertext plus the wrapped key. Expected: Only wrapped keys are persisted.
  3. On read, ask the KMS to unwrap the data key and decrypt locally. Expected: The KMS is used for key operations, not bulk data.
  4. Rotate the master key without re-encrypting data; rewrap keys on access. Expected: Rotation is cheap and incremental.
const { Plaintext, CiphertextBlob } = await kms.generateDataKey({ KeyId, KeySpec: 'AES_256' });
const ciphertext = encrypt(Plaintext, data);
await store.put(id, { ciphertext, wrappedKey: CiphertextBlob });

Verify

  • The plaintext data key exists only briefly in memory.
  • Only wrapped keys are persisted.
  • The KMS is used for key operations, not bulk data.
  • Rotation is cheap and incremental.

Limits

  • Envelope encryption depends on KMS availability; an outage can block decryption unless keys are cached.
  • It protects data at rest and wrapped keys, not the application memory where plaintext exists during processing.