Database Security
Encryption
Read aloud is unavailable in this browser.
The Last Line of Defense
Authentication controls who can connect. Authorization controls what they can access. But what happens when these defenses fail? What happens when a backup tape is stolen, a server is compromised, or network traffic is intercepted?
Encryption is the answer—the cryptographic transformation of data into an unreadable format that can only be reversed with the proper key. Well-implemented encryption means that even if an attacker obtains raw database files, backup media, or network captures, they possess nothing but meaningless ciphertext.
Database encryption isn't a single technology but a comprehensive strategy covering data at rest (stored on disk), data in transit (moving across networks), and data in use (being processed in memory). Each domain requires different techniques, and modern database systems provide sophisticated tools for all three.
By the end of this page, you will understand the cryptographic foundations underlying database encryption, master Transparent Data Encryption (TDE) for protecting data at rest, implement column-level encryption for sensitive fields, configure TLS/SSL for encrypted connections, and design key management strategies that balance security with operational requirements.
Cryptographic Foundations
Before diving into database-specific encryption, we need a solid understanding of the cryptographic primitives that underpin all encryption systems. This knowledge is essential for making informed decisions about encryption configurations.
Symmetric vs Asymmetric Encryption:
| Property | Symmetric Encryption | Asymmetric Encryption |
|---|---|---|
| Keys | Single shared secret key | Public/private key pair |
| Speed | Fast (hardware acceleration) | Slow (100-1000x slower) |
| Key Exchange | Requires secure channel | Public key can be shared openly |
| Use Cases | Bulk data encryption | Key exchange, digital signatures |
| Algorithms | AES, ChaCha20, 3DES | RSA, ECDSA, Ed25519 |
| Database Usage | Data encryption (TDE, column) | TLS handshake, certificate auth |
The AES Standard:
Advanced Encryption Standard (AES) is the foundation of virtually all modern database encryption. Key characteristics:
- Block cipher: Encrypts 128-bit blocks of data
- Key sizes: 128, 192, or 256 bits (256 recommended for sensitive data)
- Modes of operation: Define how to encrypt data larger than 128 bits
- Hardware acceleration: Modern CPUs include AES-NI instructions for near-native speed
- •CBC (Cipher Block Chaining) — Each block XORed with previous ciphertext. Requires initialization vector (IV). Sequential processing, no parallelization.
- •GCM (Galois/Counter Mode) — Counter mode with authentication tag. Provides both confidentiality and integrity. Parallelizable. Preferred for database use.
- •XTS (XEX-based Tweaked Codebook) — Designed specifically for storage encryption. Used by TDE (Transparent Data Encryption) in many databases.
- •CTR (Counter Mode) — Turns block cipher into stream cipher. Parallelizable. Used in TLS 1.3.
Key Derivation:
Raw encryption keys are typically derived from master keys or passphrases using Key Derivation Functions (KDFs). This enables:
- Generating multiple keys from a single master secret
- Adding computational cost to resist brute-force attacks
- Binding keys to specific contexts (table, column, page)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
from cryptography.hazmat.primitives.ciphers.aead import AESGCMfrom cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMACfrom cryptography.hazmat.primitives import hashesimport osimport base64 # ================================================# Key Derivation from Passphrase# ================================================ def derive_key_from_passphrase(passphrase: str, salt: bytes) -> bytes: """ Derive a 256-bit AES key from a passphrase using PBKDF2. In production, use Argon2id instead of PBKDF2. """ kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, # 256 bits salt=salt, iterations=600000, # OWASP recommendation for PBKDF2-SHA256 ) return kdf.derive(passphrase.encode()) # ================================================# AES-GCM Encryption (Recommended Mode)# ================================================ def encrypt_data(plaintext: bytes, key: bytes) -> tuple[bytes, bytes, bytes]: """ Encrypt data using AES-256-GCM. Returns (ciphertext, nonce, auth_tag embedded in ciphertext). """ # Generate random 96-bit nonce (NEVER reuse with same key!) nonce = os.urandom(12) # Create cipher instance aesgcm = AESGCM(key) # Encrypt and authenticate # GCM provides authenticated encryption - tampering is detected ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data=None) return ciphertext, nonce def decrypt_data(ciphertext: bytes, nonce: bytes, key: bytes) -> bytes: """ Decrypt AES-256-GCM encrypted data. Raises InvalidTag if tampering is detected. """ aesgcm = AESGCM(key) return aesgcm.decrypt(nonce, ciphertext, associated_data=None) # ================================================# Demonstration# ================================================ # Derive key from passphrasesalt = os.urandom(16) # Store this with encrypted datamaster_key = derive_key_from_passphrase("DB_Master_Secret_2024!", salt) # Encrypt sensitive datasensitive_data = b"SSN: 123-45-6789, Credit Card: 4111-1111-1111-1111"ciphertext, nonce = encrypt_data(sensitive_data, master_key) print(f"Plaintext: {sensitive_data}")print(f"Ciphertext: {base64.b64encode(ciphertext)}") # Store this in databaseprint(f"Nonce: {base64.b64encode(nonce)}") # Store alongside ciphertext # Decryptrecovered = decrypt_data(ciphertext, nonce, master_key)print(f"Recovered: {recovered}")assert recovered == sensitive_dataNEVER reuse a nonce/IV with the same encryption key. For GCM mode, nonce reuse completely compromises security — an attacker can recover plaintext without the key. Either use random nonces (with collision risk management) or deterministic nonces with cryptographically unique counters.
Transparent Data Encryption (TDE)
Transparent Data Encryption (TDE) encrypts database files at the storage layer, making the encryption invisible to applications. Data is encrypted when written to disk and decrypted when read into memory—automatically, without any application code changes.
What TDE Protects:
TDE is designed to protect against physical theft scenarios:
- •Stolen backup media — Database backups are encrypted; stolen tapes are useless without keys.
- •Physical server theft — Hard drives contain only ciphertext; data unreadable.
- •Improper disk disposal — Decommissioned drives don't leak data.
- •File-level access — OS administrators can't read data files directly.
- •Storage snapshots — Cloud storage snapshots are encrypted.
What TDE Does NOT Protect:
- •SQL injection — Authorized queries return decrypted data regardless of TDE.
- •Malicious DBAs — Users with database access see plaintext; TDE is transparent to them.
- •Network interception — Data in transit isn't protected by TDE (need TLS).
- •Memory access — Data is decrypted in memory; memory dumps may expose plaintext.
- •Logical backups — pg_dump, mysqldump produce plaintext (need encrypted physical backups).
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
-- ================================================-- SQL Server TDE Implementation-- ================================================ -- Step 1: Create Database Master Key (protects certificate)USE master;GOCREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Strong!MasterKey#2024';GO -- Step 2: Create certificate for TDECREATE CERTIFICATE TDECertWITH SUBJECT = 'TDE Certificate for Production';GO -- CRITICAL: Backup certificate immediately!BACKUP CERTIFICATE TDECertTO FILE = 'C:\SecureBackup\TDECert.cer'WITH PRIVATE KEY ( FILE = 'C:\SecureBackup\TDECert_PrivateKey.pvk', ENCRYPTION BY PASSWORD = 'CertBackupPassword!2024');-- Store these files SECURELY offline. Without them, -- you CANNOT restore encrypted backups! -- Step 3: Create Database Encryption Key (DEK)USE ProductionDB;GOCREATE DATABASE ENCRYPTION KEYWITH ALGORITHM = AES_256ENCRYPTION BY SERVER CERTIFICATE TDECert;GO -- Step 4: Enable TDEALTER DATABASE ProductionDBSET ENCRYPTION ON;GO -- Monitor encryption progressSELECT db.name, db.is_encrypted, dm.encryption_state, dm.percent_complete, dm.key_algorithm, dm.key_lengthFROM sys.databases dbLEFT JOIN sys.dm_database_encryption_keys dm ON db.database_id = dm.database_id; -- encryption_state values:-- 0 = No database encryption key present-- 1 = Unencrypted-- 2 = Encryption in progress-- 3 = Encrypted-- 4 = Key change in progress-- 5 = Decryption in progress-- 6 = Protection change in progressIf you lose the TDE certificate (SQL Server) or master key (MySQL/PostgreSQL), your encrypted data is PERMANENTLY UNRECOVERABLE. This is by design — there's no backdoor. Back up encryption keys to multiple secure, offline locations. Test recovery procedures regularly.
Column-Level Encryption
While TDE protects all data at rest, column-level encryption provides targeted protection for specific sensitive columns. This approach encrypts individual values within the database, maintaining encryption even when data is queried by authorized users without the decryption key.
When to Use Column-Level Encryption:
| Criterion | TDE | Column-Level |
|---|---|---|
| Protection scope | All data files | Specific columns |
| Key management | DBA manages | Application may manage |
| Performance impact | Minimal (1-5%) | Significant for encrypted columns |
| Protection from DBAs | No | Yes (if app holds keys) |
| Query capability | Full SQL support | Encrypted columns not searchable* |
| Application changes | None | Required for encrypt/decrypt |
| Regulatory compliance | Often insufficient alone | Often required for PII/PCI |
*Note: Some solutions like SQL Server's Always Encrypted support deterministic encryption for equality searches, but range queries and sorting remain impossible on encrypted columns.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
-- ================================================-- SQL Server Always Encrypted-- Encryption keys managed by client application-- ================================================ -- Step 1: Create Column Master Key (CMK)-- This references a key in Windows Certificate Store or Azure Key VaultCREATE COLUMN MASTER KEY CMK_AzureWITH ( KEY_STORE_PROVIDER_NAME = 'AZURE_KEY_VAULT', KEY_PATH = 'https://myvault.vault.azure.net/keys/AlwaysEncryptedKey/...'); -- Step 2: Create Column Encryption Key (CEK)-- Encrypted by the CMKCREATE COLUMN ENCRYPTION KEY CEK_SensitiveWITH VALUES ( COLUMN_MASTER_KEY = CMK_Azure, ALGORITHM = 'RSA_OAEP', ENCRYPTED_VALUE = 0x01700000016C006F00... -- Generated by tooling); -- Step 3: Create table with encrypted columnsCREATE TABLE Patients ( PatientID INT PRIMARY KEY, FirstName NVARCHAR(50), LastName NVARCHAR(50), -- Deterministic: allows equality comparison SSN CHAR(11) COLLATE Latin1_General_BIN2 ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = CEK_Sensitive, ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ), -- Randomized: no searching, more secure MedicalNotes NVARCHAR(MAX) ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = CEK_Sensitive, ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ), DateOfBirth DATE); -- DBA sees ciphertext:SELECT * FROM Patients;-- PatientID FirstName LastName SSN MedicalNotes-- 1 John Doe 0x016B7F8A3B2C... 0x0189AC3D7F2E... -- Application with key sees plaintext:-- (With Column Encryption Setting=Enabled in connection string)-- PatientID FirstName LastName SSN MedicalNotes-- 1 John Doe 123-45-6789 Patient presented with... -- Deterministic encryption allows equality search:SELECT * FROM Patients WHERE SSN = '123-45-6789';-- Works! Parameter is encrypted client-side, compared to encrypted valueNever store encryption keys in the database they protect. Use external key management systems (HSMs, AWS KMS, Azure Key Vault, HashiCorp Vault) with proper access controls. Rotate keys periodically and maintain audit logs of all key access. For pgcrypto, pass keys from the application layer, never store them in database objects.
Encryption in Transit (TLS/SSL)
Data at rest encryption means nothing if data is transmitted in plaintext across networks. Transport Layer Security (TLS) encrypts the communication channel between database clients and servers, protecting against:
- Eavesdropping — Attackers intercepting network traffic see only encrypted gibberish
- Credential theft — Passwords and tokens are encrypted during transmission
- Man-in-the-middle attacks — Certificate verification prevents server impersonation
- Session hijacking — Each session uses unique encryption keys
TLS Configuration Best Practices:
- •TLS 1.2 minimum, TLS 1.3 preferred — SSLv3, TLS 1.0, and TLS 1.1 are deprecated and vulnerable.
- •Strong cipher suites — AES-GCM, ChaCha20-Poly1305. Avoid CBC mode (BEAST vulnerability), RC4, 3DES.
- •Valid certificates — Certificates from trusted CAs or internal PKI. Self-signed only for development.
- •Certificate verification — Clients must verify server certificates. Don't disable verification for convenience.
- •Perfect Forward Secrecy (PFS) — ECDHE key exchange ensures past sessions remain secure if keys are compromised.
- •Certificate revocation checking — CRL or OCSP to detect compromised certificates.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
# ================================================# PostgreSQL TLS Configuration (postgresql.conf)# ================================================ # Enable SSLssl = onssl_cert_file = 'server.crt' # Server certificatessl_key_file = 'server.key' # Private key (chmod 600!)ssl_ca_file = 'ca.crt' # CA certificate for client verification # TLS version requirements (PostgreSQL 12+)ssl_min_protocol_version = 'TLSv1.2' # Minimum TLS 1.2ssl_max_protocol_version = 'TLSv1.3' # Maximum TLS 1.3 # Strong cipher suitesssl_ciphers = 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305' # Prefer server cipher suite orderssl_prefer_server_ciphers = on # ECDH curve for key exchangessl_ecdh_curve = 'prime256v1' # DH parameters file (generate with: openssl dhparam -out dhparams.pem 2048)ssl_dh_params_file = 'dhparams.pem' # Certificate Revocation List (optional)ssl_crl_file = 'root.crl'ssl_crl_dir = '/etc/ssl/crls' # ================================================# pg_hba.conf - Require SSL for connections# ================================================ # Require SSL for all remote connectionshostssl all all 0.0.0.0/0 scram-sha-256 # Require client certificate for specific usershostssl all dba_team 0.0.0.0/0 cert clientcert=verify-full # ================================================# Client Connection with TLS# ================================================ # Connection string# postgresql://user:pass@host:5432/db?sslmode=verify-full&sslrootcert=/path/to/ca.crt # psql command# PGSSLMODE=verify-full PGSSLROOTCERT=/path/to/ca.crt psql -h dbserver -U appuserSettings like TrustServerCertificate=True, sslmode=disable, or verify=false completely negate TLS security. An attacker performing a MITM attack can present any certificate. Production connections MUST validate certificates against trusted CAs.
Key Management
Encryption is only as secure as the keys protecting the data. Key management encompasses the entire lifecycle of cryptographic keys: generation, storage, distribution, rotation, and destruction. Poor key management is the most common cause of encryption failures.
Key Management Hierarchy:
Enterprise database encryption typically uses a hierarchical key structure:
Why the Hierarchy?
The hierarchical structure serves several critical purposes:
- •Minimizes HSM access — The Master Key is used only to decrypt KEKs, reducing expensive HSM operations.
- •Enables efficient rotation — Rotating a DEK requires only re-encrypting with the current KEK, not touching the HSM.
- •Supports key escrow — KEKs can be backed up encrypted under the Master Key for disaster recovery.
- •Limits blast radius — Compromise of a DEK affects only data encrypted with that key, not the entire database.
- •Facilitates compliance — Different key tiers can have different custodians, separation of duties.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
-- ================================================-- SQL Server Extensible Key Management (EKM) with Azure Key Vault-- ================================================ -- Step 1: Enable EKM and create credentialsp_configure 'EKM provider enabled', 1;RECONFIGURE; -- Register the Azure Key Vault providerCREATE CRYPTOGRAPHIC PROVIDER AzureKeyVault_EKMFROM FILE = 'C:\Program Files\SQL Server Connector for Microsoft Azure Key Vault\Microsoft.AzureKeyVaultService.EKM.dll'; -- Create credential for accessing Azure Key VaultCREATE CREDENTIAL sysadmin_ekm_credWITH IDENTITY = 'ContosoKeyVault',SECRET = 'ClientId=xxx;ClientSecret=yyy'FOR CRYPTOGRAPHIC PROVIDER AzureKeyVault_EKM; -- Map credential to loginALTER LOGIN [sa] ADD CREDENTIAL sysadmin_ekm_cred; -- Step 2: Create asymmetric key from Azure Key VaultCREATE ASYMMETRIC KEY TDE_KEYFROM PROVIDER AzureKeyVault_EKMWITH PROVIDER_KEY_NAME = 'ContosoTDEKey',CREATION_DISPOSITION = OPEN_EXISTING; -- Step 3: Create login from the asymmetric keyCREATE LOGIN TDE_Login FROM ASYMMETRIC KEY TDE_KEY;ALTER LOGIN TDE_Login ADD CREDENTIAL sysadmin_ekm_cred; -- Step 4: Use for TDEUSE ProductionDB;CREATE DATABASE ENCRYPTION KEYWITH ALGORITHM = AES_256ENCRYPTION BY SERVER ASYMMETRIC KEY TDE_KEY; ALTER DATABASE ProductionDB SET ENCRYPTION ON; -- ================================================-- Key Rotation with EKM-- ================================================ -- Rotate key in Azure Key Vault first (new version)-- Then update the database encryption key:ALTER DATABASE ENCRYPTION KEYREGENERATE WITH ALGORITHM = AES_256; -- Verify new key is in useSELECT db_name(database_id) AS DatabaseName, encryption_state_desc, key_algorithm, encryptor_type, encryptor_thumbprintFROM sys.dm_database_encryption_keys;Hardware Security Modules (HSMs) provide FIPS 140-2 Level 3 certified key protection—keys never leave the tamper-resistant hardware. Cloud KMS solutions (AWS KMS, Azure Key Vault, GCP Cloud KMS) offer HSM-backed options with easier operational management. For most organizations, cloud KMS provides sufficient security with lower operational burden.
Encryption Performance Considerations
Encryption isn't free. While modern hardware makes encryption fast, understanding the performance implications ensures informed decisions about when and how to encrypt.
Performance Factors:
| Encryption Type | Typical Overhead | Factors Affecting Performance |
|---|---|---|
| TDE (Transparent) | 1-5% | AES-NI support, I/O patterns, CPU availability |
| Column-Level (Application) | 10-30% | Encrypt/decrypt frequency, column selectivity, key retrieval |
| In-Transit (TLS) | 2-10% | Handshake frequency, cipher suite, connection pooling |
| Full-Disk Encryption | 1-3% | Storage controller encryption, SSD vs HDD |
Mitigation Strategies:
- •Use AES-NI — Modern CPUs include dedicated AES instructions. Ensure database server has AES-NI (check with
cat /proc/cpuinfo | grep aeson Linux). - •Encrypt selectively — Not all data needs encryption. Focus on PII, financial data, and regulated information.
- •Connection pooling — TLS handshakes are expensive. Maintain persistent connections to amortize handshake cost.
- •Bulk operations — Minimize encryption operations by batching. One 1MB encryption is faster than 1,000 1KB encryptions.
- •Cache decrypted data — Where permitted, cache frequently-accessed decrypted values in application memory.
- •Async encryption — For non-critical paths, perform encryption asynchronously to avoid blocking operations.
12345678910111213141516171819202122232425262728293031323334353637383940414243
-- ================================================-- Monitor TDE Encryption Performance-- ================================================ -- Check for wait types related to encryptionSELECT wait_type, wait_time_ms, waiting_tasks_countFROM sys.dm_os_wait_statsWHERE wait_type LIKE '%CRYPT%' OR wait_type LIKE '%ENCR%'ORDER BY wait_time_ms DESC; -- Monitor buffer pool for encrypted pagesSELECT database_id, COUNT(*) AS encrypted_pages, SUM(CASE WHEN is_modified = 1 THEN 1 ELSE 0 END) AS dirty_encrypted_pagesFROM sys.dm_os_buffer_descriptorsWHERE database_id > 4 -- User databasesGROUP BY database_id; -- Check encryption scan progressSELECT session_id, command, percent_complete, estimated_completion_time / 1000 / 60 AS est_minutes_remainingFROM sys.dm_exec_requestsWHERE command LIKE '%ENCRYPT%'; -- ================================================-- Monitor TLS Connection Performance-- ================================================ -- Connection distribution by encryption statusSELECT CASE WHEN encrypt_option = 'TRUE' THEN 'Encrypted' ELSE 'Unencrypted' END AS encryption_status, COUNT(*) AS connection_count, AVG(DATEDIFF(ms, connect_time, last_read)) AS avg_connection_age_msFROM sys.dm_exec_connectionsGROUP BY encrypt_option;Performance impacts vary widely by workload, hardware, and configuration. Before deploying encryption in production, benchmark with realistic data volumes and query patterns. Establish baseline metrics, enable encryption, and compare. Focus on P95/P99 latencies, not just averages.
Encryption for Compliance
Many regulations explicitly require encryption for sensitive data. Understanding compliance requirements helps determine the appropriate encryption strategy for your organization.
Regulatory Requirements:
| Regulation | Data Types | Encryption Requirements |
|---|---|---|
| PCI DSS | Cardholder data (PAN, CVV) | Must encrypt stored PAN; TLS 1.2+ for transmission; key management controls (Req 3.5-3.7) |
| HIPAA | Protected Health Information (PHI) | Addressable safeguard for data at rest; encryption provides safe harbor from breach notification |
| GDPR | Personal data of EU residents | Encryption as appropriate technical measure (Art 32); encrypted data may not require breach notification |
| SOX | Financial records | Encryption supports integrity controls; often required by audit frameworks |
| CCPA/CPRA | California consumer data | Encryption provides safe harbor from private right of action |
| FERPA | Student education records | Encryption recommended for electronic transmission and storage |
Safe Harbor Provisions:
Many regulations provide 'safe harbor' for encrypted data—if data is properly encrypted when a breach occurs, notification requirements may not apply:
- HIPAA: Data encrypted per NIST guidelines is not 'unsecured PHI'
- GDPR: Encryption may eliminate notification obligation (Art 34(3)(a))
- State breach laws: Most US states exclude encrypted data from breach notification requirements
This makes encryption not just a security measure, but a business risk mitigation strategy. The cost of encryption is often far less than the cost of breach notification, reputation damage, and regulatory fines.
Safe harbor typically applies only if encryption meets specified standards (e.g., AES-256, NIST-approved algorithms). Document your encryption architecture, key management procedures, and regular testing. This documentation is essential for demonstrating compliance during audits or in the event of an incident.
KEEP LEARNING
There’s more to understand.
You’re reading the introduction. Create a free account to read the complete lesson, save notes and keep track of your progress.