1What is the primary benefit of envelope encryption over direct encryption?
Encryption in transit (TLS) protects data as it moves between systems. Encryption at rest (AES-256, envelope encryption) protects data stored on disk. Together they ensure data confidentiality against network sniffers, stolen disks, and compromised storage systems.
Data encryption addresses two threat models: an attacker intercepting data in flight (man-in-the-middle, network sniffing) and an attacker accessing stored data (stolen hard drives, compromised backups, insider access to database files). Encryption in transit and encryption at rest are complementary -- a system that only encrypts in transit is vulnerable to data breaches from stolen storage, and a system that only encrypts at rest is vulnerable to network eavesdropping.
Encryption in transit is implemented via TLS (Transport Layer Security). TLS 1.3, finalized in 2018, provides confidentiality (AES-256-GCM encryption), integrity (HMAC), and authentication (certificate-based identity verification) for all data moving between systems. Every HTTP request, database query, cache lookup, and message queue publish should use TLS. In microservice architectures, mTLS (mutual TLS) adds client-side certificates, enabling both parties to authenticate each other. Service meshes like Istio automate mTLS by injecting sidecar proxies that handle certificate management and encryption transparently.
Encryption at rest protects data stored on disk: databases, file systems, backups, and object stores. The standard approach is envelope encryption: the data is encrypted with a Data Encryption Key (DEK) using AES-256-GCM, and the DEK is wrapped (encrypted) with a Key Encryption Key (KEK) stored in a Key Management Service (KMS). The encrypted DEK is stored alongside the encrypted data. To decrypt, the service sends the wrapped DEK to the KMS, which returns the unwrapped DEK (never exposing the KEK), and the service uses the DEK to decrypt the data.
Envelope encryption provides several security benefits. The KEK never leaves the KMS (hardware security module backed), so even a complete database breach reveals only encrypted data and encrypted DEKs. Each data object can have its own DEK (per-row, per-file, per-tenant), enabling fine-grained key rotation without re-encrypting all data. Rotating the KEK requires only re-wrapping the DEKs (fast), not re-encrypting all data (slow). KMS access is logged and auditable, providing a clear record of who decrypted what and when.
Cloud providers offer transparent encryption at rest for managed services: AWS S3 (SSE-S3, SSE-KMS), RDS (TDE), DynamoDB, Azure Storage (AES-256), and GCP Cloud Storage all encrypt data automatically. The key decision is whether to use provider-managed keys (SSE-S3), customer-managed keys (SSE-KMS with your key in AWS KMS), or customer-provided keys (SSE-C where you supply the key per request). Customer-managed keys provide more control and auditability; provider-managed keys are simpler but give less visibility into key usage.
Envelope Encryption for a User Database
When storing a user's SSN, the application generates a random DEK (AES-256 key). It encrypts the SSN with the DEK. It calls AWS KMS to wrap (encrypt) the DEK with the tenant's KEK. It stores the encrypted SSN and the wrapped DEK in the database row. To read: the application retrieves the encrypted SSN and wrapped DEK, calls KMS to unwrap the DEK, decrypts the SSN, and returns it. If the database is stolen, the attacker has encrypted SSNs and encrypted DEKs -- both useless without KMS access, which requires IAM credentials and is fully audited.
AWS (KMS + S3 SSE)
AWS KMS provides hardware-backed key management with automatic key rotation. S3 Server-Side Encryption with KMS (SSE-KMS) uses envelope encryption: S3 generates a unique DEK per object, encrypts the object, wraps the DEK with the customer's CMK (Customer Master Key) in KMS, and stores both. Every decrypt requires a KMS API call, which is logged in CloudTrail. KMS processes trillions of requests per year.
Google (Tink + Cloud KMS)
Google uses Tink, an open-source cryptographic library, for consistent encryption across all products. Tink integrates with Cloud KMS for envelope encryption and provides high-level APIs that prevent common cryptographic mistakes (e.g., reusing nonces, using ECB mode). Google encrypts all data at rest by default with AES-256, using a multi-layer key hierarchy managed by their internal KMS.
Stripe
Stripe encrypts all cardholder data (PCI scope) using envelope encryption with per-merchant keys. Each merchant's card data is encrypted with a unique DEK, wrapped by a KEK in an HSM. Stripe's infrastructure is designed so that application servers never have access to raw card numbers -- decryption happens in a dedicated, isolated tokenization service with strict access controls and comprehensive audit logging.
| Aspect | Description |
|---|---|
| Provider-Managed vs. Customer-Managed Keys | Provider-managed keys (AWS SSE-S3) are zero-effort but give you no control over key usage or audit logs. Customer-managed keys (SSE-KMS) provide audit trails, access policies, and the ability to revoke access, but add KMS API costs and latency. |
| Granularity of Encryption Keys | Per-database DEKs are simple but a single key compromise exposes everything. Per-tenant or per-row DEKs provide isolation but increase key management complexity and KMS call volume (and cost). |
| Performance vs. Security | AES-256-GCM hardware acceleration makes bulk encryption fast (<1% overhead on modern CPUs). But KMS calls for envelope encryption add 5-20ms latency per decrypt. Caching unwrapped DEKs in memory reduces latency but increases exposure if the process is compromised. |
| Application-Level vs. Storage-Level Encryption | Storage-level encryption (disk encryption, S3 SSE) is transparent to the application but does not protect against application-level breaches (SQL injection returns plaintext). Application-level encryption (encrypt before writing) protects against both but requires code changes and key management integration. |
Capital One Breach: Why Encryption at Rest Was Not Enough
Scenario
In 2019, Capital One suffered a data breach affecting 100 million customers. The attacker exploited a misconfigured WAF (Web Application Firewall) to gain temporary AWS credentials via the EC2 instance metadata service. With these credentials, the attacker accessed S3 buckets containing customer data.
Solution
The data in S3 was encrypted at rest (SSE-S3), but the attacker had valid IAM credentials (from the compromised EC2 role) and could decrypt the data because the role had KMS decrypt permissions. The lesson: encryption at rest protects against physical theft but not against credential compromise. Defense-in-depth requires: IAM least privilege (the WAF role should not have S3 access), network segmentation (restrict metadata service access), and application-level encryption with separate key policies per data classification.
Outcome
Capital One paid $80M in fines and $190M in settlements. The incident led to AWS releasing IMDSv2 (requires session tokens, blocking the metadata SSRF attack). The broader industry lesson: encryption at rest is necessary but not sufficient. Key access policies must follow least privilege, and IAM role permissions must be scoped to the minimum needed. Application-level encryption with per-tenant keys would have limited the breach to one tenant at a time.
See Encryption at Rest & in Transit in action
Explore system design templates that use encryption at rest & in transit and run traffic simulations to see how these concepts perform under real load.
Browse Templates1What is the primary benefit of envelope encryption over direct encryption?
2Why was encryption at rest insufficient to prevent the Capital One data breach?