Envelope encryption
Lesson 1 of 5 in KMS, Keys, and Certificates.
Nearly every “encrypted with KMS” sentence in AWS is shorthand for the same three-step pattern, and the exam expects you to know it in detail rather than as a slogan.
A client asks AWS KMS for a data key. KMS generates a fresh symmetric key and returns it twice: once in plaintext, and once encrypted under a KMS key you named. The client encrypts the actual data — the 4 GB video, the database page, the S3 object — locally with the plaintext data key, then throws the plaintext copy away and stores the encrypted data key next to the ciphertext. To read the data back, the client sends the encrypted data key to KMS, gets the plaintext key returned, decrypts, and discards the plaintext again. That pattern is envelope encryption: the data sits in an envelope sealed by the data key, and the data key sits in an envelope sealed by the KMS key.
Three properties fall out of that design, and each one answers a different exam question. Your plaintext never reaches KMS — only keys do, so no amount of data volume changes the trust boundary. Large objects never cross the KMS API, which matters because the KMS Encrypt operation accepts at most 4 KB of data; without the envelope you simply could not encrypt a 4 GB object with KMS at all. And decryption costs one small API call regardless of object size, so throughput scales with your own CPU rather than with a remote service.
Two API details are worth memorising because questions turn on them.
GenerateDataKey returns the plaintext and the encrypted copy together, which is what a writer needs. GenerateDataKeyWithoutPlaintext returns only the encrypted copy — the right call for a component that must provision an envelope it is not allowed to open, such as a control plane that prepares keys for workers that will each call Decrypt later. And the plaintext data key is the one secret your own code is responsible for: hold it for the duration of the operation, overwrite the buffer, never log it, never write it to disk, never put it in an environment variable. KMS cannot protect a key you left in a heap dump.
Encryption context is the other half of the mechanism and the part teams skip. It is a set of non-secret key–value pairs passed at encrypt time, bound into the ciphertext as additional authenticated data. Decryption fails unless the identical context is supplied again — so a ciphertext encrypted with {"tenant":"acme"} cannot be decrypted by code claiming {"tenant":"globex"}, even when both callers may use the key. Because the pairs appear in CloudTrail, they turn opaque Decrypt events into an audit trail you can query, and because they can be matched in policy with the kms:EncryptionContext: condition keys, they let one key serve many tenants with per-tenant authorization.
A horizontal bar chart of bytes sent to the AWS KMS API when protecting objects of different sizes with envelope encryption: a 4 kilobyte object sends about 300 bytes, a 4 megabyte object sends about 300 bytes, a 4 gigabyte object sends about 300 bytes, and a 4 terabyte object sends about 300 bytes. A fifth bar shows the alternative of sending data directly to the KMS Encrypt operation, which is capped at 4096 bytes of plaintext and therefore cannot carry any of the larger objects at all. The teaching point is that the request size is a function of the wrapped data key, not of the data.
Key terms: Envelope encryption, Data key, Encryption context, KMS customer managed key (CMK)
Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.