Encryption at Rest

Database Security

Chapter 5 · Encryption at Rest

Chapter 4 secured the network path to a running database. This chapter addresses a different question entirely: what if someone gets the raw storage itself — a stolen drive, a leaked cloud snapshot, or (Chapter 8's subject) an unprotected backup file? Encryption at rest is the answer to that scenario specifically.

What "At Rest" Means & The Threat It Addresses

Data "at rest" is data sitting on disk — data files, backups, snapshots — as opposed to data moving across a network (in transit, Chapter 6's subject). The threat model here is specific: someone obtains the physical or virtual storage medium itself, bypassing the network and the application entirely — a stolen laptop or server, a decommissioned drive that was never wiped, or a cloud storage snapshot that leaked or was misconfigured to be publicly readable.

Full-Disk Encryption

Full-disk encryption (e.g. LUKS on Linux, or a cloud provider's built-in encrypted-volume option) encrypts the entire disk or volume at the operating-system level — completely transparent to the database running on top of it, requiring no application or query changes at all.

Full-disk encryption doesn't protect a running, unlocked server
Full-disk encryption protects data specifically when the disk is powered off or physically removed — a stolen drive is unreadable without the decryption key. It does not protect against someone with legitimate OS-level or database-level access to a running system: while the server is up, the disk is already unlocked and decrypted, and anything readable through the OS or database is readable in plain form. This is a defense against physical theft specifically, not against a compromised running system.

Transparent Data Encryption (TDE)

TDE moves encryption one level down from the OS into the database engine itself — data files, logs, and the backups the engine produces are encrypted, decrypting automatically and transparently ("transparent" is literally the name) for any authenticated query. Available as a built-in or extension feature in most major engines (MySQL Enterprise, SQL Server, Oracle, PostgreSQL extensions).

TDE is closer to the data than full-disk encryption — it protects the database's own files specifically, even if they're copied out independently of the disk itself — but shares the exact same fundamental limitation: it decrypts automatically for any authenticated connection. A compromised database account, or a successful SQL injection, reads exactly the same plaintext TDE would have hidden from a stolen disk.

Column-Level Encryption

For especially sensitive individual fields — a Social Security number, a full credit card number — column-level encryption encrypts that specific value, typically at the application layer, such that even a legitimate, authenticated database query returns ciphertext unless the requesting code also independently holds the decryption key.

-- MySQL's built-in AES functions, illustrating the pattern INSERT INTO customers (name, ssn_encrypted) VALUES ('Dana', AES_ENCRYPT('123-45-6789', @encryption_key)); -- reading it back requires the SAME key, known only to authorized application code SELECT name, AES_DECRYPT(ssn_encrypted, @encryption_key) FROM customers;

This is the one technique in this chapter that provides genuine defense against a compromised or overprivileged database account itself (Chapter 3's threat model) — a database account with full SELECT access still only ever sees ciphertext for that column without the separate encryption key. The trade-off: encrypted columns generally can't be indexed, searched, or sorted on directly by the database, since the stored value is no longer the real one.

TDE / Full-Disk EncryptionColumn-Level Encryption
Protects againststolen physical/virtual storage mediaa compromised or overprivileged database account
Transparent to queries?yes — fully automaticno — requires the application to hold the key
Costessentially noneloses indexing/searching/sorting on that column

Key Management Basics

Every technique above is only as strong as how its encryption key is protected — and the single most common mistake is storing that key right next to the data it encrypts (a key in the same config file, the same server, the same repository), which defeats the entire purpose: whoever obtains the data also obtains the key needed to read it.

  • Never hardcode an encryption key in application source or commit it to version control — the same discipline this site has stressed for database connection strings (mongodb2-7) and CI/CD secrets (pipelines1-5) applies directly to encryption keys.
  • Use a dedicated key management service (a cloud KMS, HashiCorp Vault) that stores keys separately from both the application and the data, with its own access controls and audit trail.
  • Rotate keys periodically — a leaked key that's rotated regularly has a bounded window of usefulness to an attacker, rather than being valid indefinitely.
Encryption without real key management is just obfuscation
Encrypting data next to a key anyone with access to that data can also read isn't meaningfully different from not encrypting it at all — it adds a technical step, not a real security boundary. The genuine security value of encryption at rest comes entirely from the key being stored, managed, and access-controlled separately from the data it protects.

Hands-On Exercises

Exercise 1

Explain why full-disk encryption protects against a stolen server but does not protect against a compromised database account on a running system. What specifically is different about the two scenarios?

📄 View solution
Exercise 2

A team stores customer credit card numbers as plain columns, protected only by TDE. A developer with legitimate read access to the customers table (per Chapter 3's least privilege) can still read every card number in plaintext. Propose the fix from this chapter, and explain the trade-off it introduces.

📄 View solution
Exercise 3

A company encrypts a sensitive column, but stores the encryption key in the same application config file as the database connection string, both committed to the same private Git repository. Explain why this setup provides little real security benefit.

📄 View solution

Chapter 5 Quick Reference

  • At rest = data on disk (files, backups, snapshots); in transit = data moving over a network (Chapter 6)
  • Full-disk encryption protects a powered-off/stolen drive; useless against a compromised running system, where the disk is already unlocked
  • TDE encrypts the database engine's own files/backups transparently — same fundamental limitation as full-disk encryption: decrypts automatically for any authenticated query
  • Column-level encryption is the one technique that defends against a compromised/overprivileged DB account itself — at the cost of losing indexing/search/sort on that column
  • Never store an encryption key next to the data it protects — use a dedicated key management service, never a hardcoded key in config or source
  • Encryption without real key management is obfuscation, not security
  • Next chapter: Encryption in Transit — TLS for database connections, certificate verification, why an unencrypted connection over a network is a real risk