Scrambling data so that stealing it isn’t enough to read it. Two places it matters — while it moves and while it sits — and the part everyone gets wrong is key management.
Prerequisites: HTTP & TLS, AuthN vs AuthZ Time to read: ~20 minutes
Data exists in two states, and each needs protecting:
🚨 You need both. TLS protects the wire but the database stores plaintext; disk encryption protects the disk but the network is exposed. A breach can come from either direction, and encrypting one without the other leaves an open door.
(There’s a third, harder state — in use, data in memory while being processed — addressed by confidential computing / enclaves, still niche. Worth knowing the term.)
Two kinds of encryption, and knowing the difference is fundamental.
Symmetric — one key encrypts and decrypts. Fast.
AES-256: encrypt(plaintext, key) → ciphertext
decrypt(ciphertext, key) → plaintext (same key)
✅ Very fast (hardware-accelerated). Used for the actual bulk data. ❌ 🚨 The key distribution problem: both sides need the same secret key, so how do you share it securely over an insecure network? You can’t just send it — anyone watching gets it too.
Asymmetric (public-key) — a pair: a public key encrypts, a private key decrypts (or vice versa for signing). Slow.
RSA / ECDSA: encrypt(plaintext, PUBLIC key) → ciphertext
decrypt(ciphertext, PRIVATE key) → plaintext
✅ Solves key distribution — publish the public key freely; only the private-key holder can decrypt. Also enables digital signatures (sign with private, anyone verifies with public). ❌ Slow — impractical for bulk data.
🚨 The insight that makes TLS work: use both. Asymmetric to exchange a symmetric key securely, then symmetric for the actual data. You get asymmetric’s safe key distribution and symmetric’s speed.
1. Asymmetric key exchange establishes a shared symmetric "session key" (slow, once)
2. Symmetric encryption with that session key for all the data (fast, ongoing)
This hybrid is exactly what the TLS handshake does.
Covered in depth in HTTP & TLS; the security essentials:
TLS gives you three things (not just secrecy):
🚨 Authentication is the part people forget. Encryption without authentication means you’ve securely connected to an attacker — a man-in-the-middle. Certificates, signed by a trusted CA, are what prove the server is who it claims. Encryption alone isn’t enough.
Practical requirements:
mTLS (mutual TLS) — both sides present certificates, so the client is authenticated too. Standard for service-to-service auth inside a mesh, and a strong answer to “how do services authenticate each other?”
Protecting stored data. Several layers, and they compose:
1. Full-disk / volume encryption. The whole disk is encrypted (LUKS, BitLocker, cloud
EBS encryption). ✅ Transparent, protects against stolen disks and improperly-wiped hardware. ❌ 🚨
Doesn’t protect against much — if an attacker has access to the running system (SQL injection, a
compromised app), the OS decrypts transparently and they read plaintext. Disk encryption protects the
physical medium, not a live application breach.
2. Database-level (Transparent Data Encryption, TDE). The database encrypts its files. Same limitation — transparent to authenticated queries, so an app-level breach still reads plaintext. Protects backups and stolen files.
3. Application-level / field-level encryption. 🚨 The strongest, and the one that matters most for sensitive data. The application encrypts specific fields before storing them, so the database only ever sees ciphertext.
# The database stores ciphertext; a DB breach reveals nothing
encrypted_ssn = encrypt(user.ssn, field_key)
db.save(encrypted_ssn)
✅ Protects even against a full database compromise, a malicious DBA, or a leaked backup — the data is useless without the application’s keys, which live elsewhere. ❌ Can’t index or search encrypted fields normally, more complex, and key management is critical.
🎙️ “Full-disk encryption for the baseline, but for the sensitive fields — SSNs, payment data — I’d use application-level encryption so the database only ever holds ciphertext. Disk and TDE encryption are transparent to an authenticated breach; field-level isn’t.”
This distinction — disk/TDE protects the medium, field-level protects against a live breach — is a strong interview point.
Encryption is only as strong as your key management, and this is where systems fail. Encrypting data with a key stored next to the data protects nothing — the attacker who gets the data gets the key.
The essentials:
A dedicated key manager. Keys live in a KMS (AWS KMS, GCP KMS, Azure Key Vault) or an HSM (Hardware Security Module — tamper-resistant hardware where keys never leave). 🚨 The application never sees the master key. It asks the KMS to encrypt/decrypt, or to unwrap a data key.
Envelope encryption — the standard pattern, worth knowing:
1. A master key (in the KMS, never extracted) encrypts...
2. ...a data key, which encrypts the actual data.
3. Store the encrypted data + the encrypted data key together.
4. To decrypt: ask the KMS to decrypt the data key, then use it locally.
🚨 Why: the fast symmetric data key does the bulk work locally, but it’s protected by the master key that never leaves the KMS. And rotating the master key doesn’t require re-encrypting all your data — just re-wrapping the data keys.
Key rotation. Keys are rotated periodically (and immediately on suspected compromise). Envelope encryption makes this cheap.
Separation. 🚨 The keys must be stored separately from the data, with separate access controls. A leaked database backup must not also leak the keys.
Never in code or config. Keys and secrets in git, in environment files, or hardcoded are a breach. → Secrets Management
🚨 A common confusion, and an interview trap.
| Encryption | Hashing | |
|---|---|---|
| Reversible? | ✅ Yes (with the key) | ❌ No — one-way |
| Purpose | Protect data you need to read back | Verify without storing the original |
| Use for | PII, messages, files, anything you retrieve | Passwords, integrity checks, deduplication |
🚨 Passwords are hashed, never encrypted — you never need to read a password back, only verify a submitted one matches. Encrypting passwords means a stolen key exposes them all; hashing (with a slow, salted algorithm like bcrypt/Argon2) means even the breach can’t reverse them. → AuthN
Encrypt data you must retrieve (SSNs, card numbers you charge again, messages). Hash data you only verify (passwords).
Prioritize by sensitivity and compliance:
⚖️ Encryption isn’t free — CPU cost, latency, key-management operational burden, and encrypted fields you can’t query. But the cost of not encrypting sensitive data is a breach, a regulatory fine, and lost trust. For sensitive data the trade is clear; for a public product catalogue, encrypting it at rest adds cost for little benefit. Encrypt by sensitivity, not uniformly.
| Choice | Gain | Cost |
|---|---|---|
| TLS everywhere | Confidentiality, integrity, authentication | Handshake latency (small with 1.3), cert management |
| Disk/TDE encryption | Protects stolen media and backups | Transparent to a live app breach — limited protection |
| Field-level encryption | Survives a full DB compromise | Can’t index/search; complexity; key management |
| Envelope encryption | Cheap rotation; master key never leaves KMS | KMS dependency and cost |
| mTLS internally | Service-to-service authentication | Certificate lifecycle to manage |
1. Hybrid encryption by hand. Encrypt a large file with AES (symmetric), then encrypt the AES key with RSA (asymmetric). To decrypt: RSA-decrypt the key, then AES-decrypt the file. This is TLS’s model in miniature, and building it makes the “why both” point obvious.
2. Prove disk encryption’s limitation. Set up a database with disk encryption. Then run a query as an authenticated user (or simulate a SQL injection) and confirm you read plaintext — the disk encryption did nothing. Then encrypt a field at the application level and confirm the same query now returns ciphertext.
3. Use envelope encryption. With a cloud KMS (or a local mock), generate a data key, encrypt data with it locally, and store the data key encrypted by the KMS master key. Then decrypt: ask the KMS to unwrap the data key, use it locally. Note that the master key never left the KMS.
4. See a cert. openssl s_client -connect example.com:443 — inspect the certificate chain, the
expiry, and the cipher negotiated. Then check the expiry date and imagine the outage if nobody renews
it.