How wrapped-key encryption protects data at scale
A small encrypted key beside each ciphertext looks redundant until rotation, access control, and KMS outages expose what that extra layer buys.
- Published
- Reading time
- 14 min read
Wrapped-key encryption solves a practical problem: the key that encrypts application data needs protection of its own.
Encrypting every record directly with one long-lived master key looks simpler. It also spreads one key across a large amount of data, ties bulk encryption to the system that holds the master key, and makes changes to that key expensive. Wrapped-key encryption inserts a deliberate second layer. A scoped data encryption key encrypts the data. A separately managed key encryption key encrypts, or wraps, that data key.
The result is commonly called envelope encryption. “Key wrapping” has a narrower cryptographic meaning, while envelope encryption describes the complete design around data and keys. The distinction matters when choosing an API, but both terms point to the same useful separation: data keys handle data; wrapping keys protect data keys.
This article explains what that extra layer buys, what it costs, and where implementations tend to go wrong.
The two keys have different jobs
A data encryption key, usually shortened to DEK, is a symmetric key generated for a limited unit of data. That unit might be one record, one object, one tenant, or one storage segment. The application uses the DEK with an authenticated-encryption algorithm such as AES-GCM to produce ciphertext and an authentication tag.
A key encryption key, or KEK, protects the DEK. The KEK normally lives behind a key management system or hardware security module. Rather than handing the KEK to application code, the service exposes operations that wrap and unwrap data keys under an identity and access policy.
The stored envelope usually contains:
- The encrypted application data.
- The wrapped DEK.
- A nonce or other initialization value required by the data cipher.
- An authentication tag, unless the cipher format already includes it.
- A format version and a stable reference to the wrapping key.
- Any non-secret metadata needed to reconstruct authenticated context.
The wrapped DEK does not need to be hidden from the database. Its confidentiality and integrity come from the KEK and wrapping operation. Keeping it beside the ciphertext often makes backup, replication, and retrieval easier because the pieces travel together.
How an encryption operation works
A typical write follows five steps:
- Generate a fresh, random DEK with a cryptographically secure random-number generator.
- Encrypt the plaintext locally with that DEK and an authenticated cipher.
- Ask the KMS to wrap the DEK with the selected KEK.
- Store the ciphertext, wrapped DEK, nonce, tag, version, and key reference as one logical envelope.
- Remove the plaintext DEK from application memory as soon as the runtime permits.
Reading reverses the flow. The application loads the envelope, sends the wrapped DEK to the KMS for unwrapping, and uses the returned plaintext DEK to authenticate and decrypt the ciphertext locally.
Google Cloud’s envelope-encryption guidance recommends generating DEKs locally, storing them only in encrypted form, keeping each near the data it encrypts, and managing the smaller set of KEKs centrally. Google Tink can implement this flow with its KMS envelope AEAD API, including generation of a fresh DEK and storage of its wrapped form in the ciphertext.
The exact serialization is part of the security design. A format should say which algorithm and version produced the envelope instead of asking future code to guess. It should also reject unknown versions rather than silently falling back to unsafe behavior.
Why not send all data through the KMS?
Key management services are designed to protect and control keys, not to act as high-throughput storage ciphers. They often limit request size and charge or throttle by operation. Sending a large file to a remote KMS also adds network latency and puts plaintext on another service boundary.
Envelope encryption keeps bulk work local. The application performs fast symmetric encryption close to the data and asks the KMS to process only a small DEK. A large object and a short database field create roughly the same KMS payload.
This separation is also useful when the application must encrypt while disconnected from the KMS for short periods, although such caching needs a strict threat model. Reusing or caching plaintext DEKs reduces KMS traffic but increases the amount of data exposed by one key and keeps sensitive material in memory longer. Availability cannot be improved for free.
The concrete benefits
Smaller key-management surface
A system may create millions of DEKs while managing only tens or hundreds of KEKs. The KMS can concentrate access policies, audit events, rotation schedules, and hardware protection on that smaller set. Applications do not need one centrally registered master key per record.
This is management efficiency, not fewer cryptographic keys. The many DEKs still exist, but only in wrapped form outside active operations.
Separation between data and key custody
OWASP recommends storing keys separately from encrypted data where possible in its Cryptographic Storage Cheat Sheet. An attacker who obtains only a database backup should not also receive the KEK needed to unwrap its data keys.
That boundary becomes meaningful only if credentials and permissions are also separate. If the same compromised application process can read every ciphertext and ask the KMS to unwrap every DEK, the KMS has not prevented that process from decrypting data. It may still provide audit logs and block offline decryption of a stolen database, but it does not turn an authorized runtime into an untrusted one.
More practical rotation
Without an envelope, replacing a key can require decrypting and re-encrypting every byte of application data. With wrapped keys, the bulk ciphertext can remain unchanged while each DEK is unwrapped under an old KEK and wrapped under a new one.
That can reduce data movement substantially, but the work does not disappear. Every affected envelope still needs a safe migration. Old KEK versions must remain available until migration and validation finish. The process needs checkpoints, retries, counts, and a tested rollback or recovery plan.
Many systems use an even simpler first step: new writes use the current KEK, while readers retain access to old KEK versions. Rewrapping then happens gradually. Rotation policy should distinguish creating a new KEK version, directing new encryption to it, rewrapping old DEKs, and eventually disabling or destroying old versions. Those are separate actions.
Finer containment
A fresh DEK per record or object limits how much ciphertext shares one data key. A tenant-level or segment-level DEK costs less to unwrap and cache but exposes a larger set if that DEK leaks. There is no universally correct granularity.
The useful question is concrete: how much data should one recovered DEK reveal, and how many KMS operations can this workload afford? Google Cloud explicitly recommends choosing DEK granularity according to the workload rather than treating one pattern as mandatory.
Central policy and auditability
A KMS can decide which workload identity may use a KEK, for which operations, and under which conditions. It can also produce an audit trail for unwrap attempts. This is much easier to inspect than master keys copied into application configuration across many hosts.
Audit logs are evidence, not prevention. They need retention, alerting, and identities narrow enough to make events meaningful. A log saying that a broad production role unwrapped a key is less useful than one identifying a specific workload and purpose.
What wrapped keys do not solve
Envelope encryption protects a specific boundary. It does not provide complete data security.
It does not replace authorization. A caller must still be allowed to read the record and invoke decryption. It does not protect plaintext while an authorized application is processing it. It does not remove secrets from process memory, crash dumps, traces, or logs. It does not make backups recoverable after someone destroys the only usable KEK. It does not make encrypted values searchable without an additional, carefully designed index. It also does not protect passwords, which should normally be stored with a password-hashing function rather than reversible encryption.
Authenticated encryption matters too. Confidentiality alone does not detect a modified ciphertext or swapped wrapped key. AES-GCM is one established authenticated mode described by NIST SP 800-38D. Nonces must follow the chosen algorithm’s rules, and additional authenticated data must be stable and reproducible.
AAD can bind an envelope to context such as a tenant ID, record ID, and field name. If an attacker copies ciphertext into another row, authentication then fails. AAD is not secret, does not stop replay in the same context, and can make data undecryptable if it depends on mutable values.
Key wrapping is more specific than ordinary encryption
Developers sometimes use “wrap” to mean any encryption of a key. Standards use it more precisely. NIST SP 800-38F defines approved methods for protecting both the confidentiality and integrity of cryptographic keys, including AES Key Wrap and AES Key Wrap with Padding.
A managed KMS may expose a dedicated wrapping operation, an authenticated-encryption operation used for a DEK, or a data-key API that returns plaintext and encrypted copies together. Follow the provider’s documented construction. Do not improvise by feeding raw key bytes into an unauthenticated cipher mode, and do not assume that an API named encrypt automatically implements a standard key-wrap format.
Interoperability depends on the exact algorithm, padding, metadata, and byte encoding. This matters during provider migration and disaster recovery. Test that a restored system can actually unwrap representative historical envelopes, not merely that it can list the KEK.
Operational costs worth planning for
The extra layer introduces state and failure modes:
- Each envelope is larger because it carries a wrapped DEK and metadata.
- Decryption may require a network call, adding latency, cost, throttling, and an availability dependency.
- Caching DEKs changes the exposure window and complicates eviction.
- Destroying or disabling a KEK can make every dependent envelope unreadable.
- Restores must preserve the relationship among ciphertext, wrapped DEK, key version, and authenticated context.
- Rotation and rewrapping need observable migration jobs rather than a configuration toggle.
- Access to unwrap keys is highly sensitive and should not be granted merely because a workload can encrypt.
Google Tink’s documentation makes one trade-off explicit: its envelope API handles a fresh DEK automatically but performs a KMS request for every encryption and decryption. An alternative protects a longer-lived keyset with the KMS and can reduce calls, at the cost of more key handling and a wider effect if that keyset is exposed.
These costs do not negate the design. They explain why the right unit for a DEK depends on throughput, failure tolerance, and the amount of data one key may expose.
A review checklist
Before shipping an envelope-encryption design, I would want clear answers to these questions:
- What exact data is sensitive, and against which plausible disclosure are we protecting it?
- Where are DEKs generated, and how long can plaintext DEKs remain in memory?
- What is the DEK granularity, and how much data does one leaked DEK expose?
- Which authenticated-encryption and wrapping constructions does the implementation use?
- How are nonces generated and prevented from repeating under one key?
- Which stable values become AAD, and can they be reconstructed after a restore or migration?
- Can the application encrypt without permission to decrypt where the workflow permits it?
- What happens to reads when the KMS is slow, unavailable, throttled, or returns an unknown key error?
- How do new KEK versions, gradual rewrapping, disabling, and destruction differ operationally?
- Can a restore test decrypt old envelopes with restored KMS access and metadata?
- Do logs, traces, exceptions, and crash reports exclude plaintext and key material?
- Which metric or audit event reveals unusual unwrap volume?
If these answers live only in the encryption function, the system is not ready. Key management crosses application code, identity, storage, backups, monitoring, and incident response.
Use the extra layer for a reason
Wrapped-key encryption is valuable because DEKs and KEKs live different lives. DEKs can be numerous, narrow, and close to ciphertext. KEKs can be scarce, centrally controlled, audited, and protected by a KMS or hardware boundary.
That separation makes large-data encryption efficient, limits some forms of key exposure, and gives rotation a tractable path. It also adds metadata, service calls, migrations, and a dangerous dependency on the availability and recoverability of wrapping keys.
Use it when those boundaries address a stated threat model. For a small application, a well-protected local key and a sound authenticated-encryption library may be the simpler correct answer. For systems with many records, several workloads, centralized access policy, or regular key rotation, the wrapped-key pattern earns its extra moving parts.
I use this pattern in KMS, which grew from an Elixir application into its own project. The implementation details differ across providers and libraries, but the architectural question stays the same: which key should protect the data, and which boundary should protect that key?
Try the pattern with KMS
KMS is available on Hex as one OTP application:
defp deps do
[
{:kms, "~> 0.1.0"}
]
end
Use it as an embedded library in the same BEAM, or enable its HTTP API and run it as a separate key-management service. The KMS documentation starts with the embedded setup and explains when the remote boundary is worth operating. The source is on GitLab. Try the embedded example first, then move the service boundary only if your threat model requires it.