# 600 Reference 43a68fe5

> Encryption at Rest Reference

- Skill: `tools-only/600-reference-43a68fe5` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/600-reference-43a68fe5`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/600-reference-43a68fe5/raw
- Safety review: pending (external: skill-scanner FAIL, skillspector WARNING)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/600-reference-43a68fe5

---

# Encryption at Rest Reference

Comprehensive technical reference for encryption at rest, key management, and compliance standards.

## Table of Contents

1. [Fundamentals](#fundamentals)
2. [Encryption Algorithms](#encryption-algorithms)
3. [Key Management](#key-management)
4. [Envelope Encryption](#envelope-encryption)
5. [Database Encryption](#database-encryption)
6. [File and Disk Encryption](#file-and-disk-encryption)
7. [Cloud KMS Integration](#cloud-kms-integration)
8. [Key Rotation](#key-rotation)
9. [Compliance Standards](#compliance-standards)
10. [Performance Considerations](#performance-considerations)
11. [Common Patterns](#common-patterns)
12. [Anti-Patterns](#anti-patterns)
13. [Security Best Practices](#security-best-practices)
14. [Implementation Examples](#implementation-examples)

---

## Fundamentals

### What is Encryption at Rest?

**Encryption at rest** protects data stored on disk from unauthorized access. Unlike encryption in transit (TLS/SSL), encryption at rest protects data when it's not actively being transmitted.

**Key Differences**:

| Aspect | Encryption at Rest | Encryption in Transit |
|--------|-------------------|----------------------|
| **Protects** | Stored data on disk | Data moving over network |
| **Threat Model** | Physical access, disk theft, backups | Network eavesdropping, MITM |
| **Typical Use** | Databases, files, backups, volumes | HTTPS, TLS, SSH |
| **Performance** | One-time cost on read/write | Continuous overhead during transmission |
| **Key Lifetime** | Long-lived (months/years) | Short-lived (session keys) |

### Threat Model

**What encryption at rest protects against**:
- **Physical theft**: Stolen laptops, hard drives, backup tapes
- **Cloud provider access**: Unauthorized access by cloud staff
- **Forensic recovery**: Data recovery from decommissioned drives
- **Backup compromise**: Stolen or leaked backup files
- **Snapshot access**: Unauthorized access to volume snapshots
- **Insider threats**: Malicious employees with physical access

**What it does NOT protect against**:
- **Application-level attacks**: SQL injection, XSS, CSRF
- **Authorized user access**: Users with valid credentials
- **Memory dumps**: Data in RAM is not encrypted
- **Side-channel attacks**: Timing attacks, cache attacks
- **Compromised encryption keys**: If attacker has keys, encryption is useless

### Encryption Layers

```
┌─────────────────────────────────────────┐
│ Application-Level Encryption            │  ← Column/field encryption (highest control)
├─────────────────────────────────────────┤
│ Database-Level Encryption               │  ← TDE (Transparent Data Encryption)
├─────────────────────────────────────────┤
│ Filesystem-Level Encryption             │  ← eCryptfs, EncFS
├─────────────────────────────────────────┤
│ Volume/Block-Level Encryption           │  ← LUKS, dm-crypt, BitLocker
├─────────────────────────────────────────┤
│ Hardware-Level Encryption               │  ← Self-encrypting drives (SEDs)
└─────────────────────────────────────────┘
```

**Trade-offs**:

| Layer | Granularity | Performance | Key Management | Flexibility |
|-------|-------------|-------------|----------------|-------------|
| Application | Per-field | Slowest | Most complex | Highest |
| Database | Per-database | Fast | Moderate | Moderate |
| Filesystem | Per-file | Moderate | Moderate | Moderate |
| Volume | Per-volume | Fast | Simple | Low |
| Hardware | Per-drive | Fastest | Simple | Lowest |

### When to Use Each Layer

**Application-Level**:
- Need per-field encryption (e.g., credit card numbers)
- Compliance requires end-to-end encryption
- Different users need different keys
- Zero-trust architecture

**Database-Level**:
- Encrypt entire database with minimal code changes
- Compliance requires encryption at rest
- Centralized key management
- Performance is critical

**Filesystem-Level**:
- Encrypt user directories or shared folders
- Protect files from OS-level access
- Need per-user encryption

**Volume-Level**:
- Encrypt entire disk/partition
- Protect against physical theft
- Simplest to implement
- Minimal performance overhead

**Hardware-Level**:
- Best performance
- No OS support required
- Limited key management control

---

## Encryption Algorithms

### Symmetric Encryption

**Definition**: Same key used for encryption and decryption.

**Use Case**: Encryption at rest (fast, efficient).

#### AES (Advanced Encryption Standard)

**Overview**:
- **Standard**: FIPS 197 (2001)
- **Block Size**: 128 bits
- **Key Sizes**: 128, 192, 256 bits
- **Status**: Industry standard, NIST approved

**Modes of Operation**:

| Mode | Properties | Use Case | Security |
|------|-----------|----------|----------|
| **ECB** (Electronic Codebook) | Deterministic, no IV | ❌ NEVER USE | Insecure |
| **CBC** (Cipher Block Chaining) | Requires IV, sequential | Legacy systems | Secure with IV |
| **CTR** (Counter) | Parallel, requires nonce | Performance-critical | Secure with unique nonce |
| **GCM** (Galois/Counter Mode) | AEAD, parallel, auth tag | Modern apps | Best choice |
| **XTS** (XEX-based tweaked-codebook) | Disk encryption | Full-disk encryption | Optimized for storage |

**Recommended**: **AES-256-GCM** (authenticated encryption with associated data).

**Example (OpenSSL)**:
```bash
# Encrypt file with AES-256-GCM
openssl enc -aes-256-gcm -salt -in plaintext.txt -out encrypted.bin -k password

# Decrypt
openssl enc -aes-256-gcm -d -in encrypted.bin -out plaintext.txt -k password
```

**Python Example (cryptography library)**:
```python
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

# Generate key (256 bits)
key = AESGCM.generate_key(bit_length=256)
aesgcm = AESGCM(key)

# Generate nonce (96 bits recommended for GCM)
nonce = os.urandom(12)

# Encrypt
plaintext = b"Secret data"
ciphertext = aesgcm.encrypt(nonce, plaintext, None)

# Decrypt
decrypted = aesgcm.decrypt(nonce, ciphertext, None)
assert decrypted == plaintext
```

**Go Example**:
```go
package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "io"
)

func encryptAESGCM(plaintext, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }

    aesGCM, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }

    nonce := make([]byte, aesGCM.NonceSize())
    if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
        return nil, err
    }

    // Prepend nonce to ciphertext
    ciphertext := aesGCM.Seal(nonce, nonce, plaintext, nil)
    return ciphertext, nil
}
```

**Performance**:
- **Hardware acceleration**: AES-NI (Intel), ARMv8 Crypto Extensions
- **Throughput**: 2-10 GB/s with hardware acceleration
- **Latency**: ~1-5 microseconds per operation

#### ChaCha20-Poly1305

**Overview**:
- **Standard**: RFC 8439 (2018)
- **Algorithm**: Stream cipher (ChaCha20) + MAC (Poly1305)
- **Key Size**: 256 bits
- **Nonce Size**: 96 bits (12 bytes)
- **Use Case**: Mobile devices without AES-NI, software-only systems

**Advantages over AES**:
- Faster on systems without AES-NI
- Constant-time implementation (resistant to timing attacks)
- Simpler to implement correctly

**Python Example**:
```python
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
import os

# Generate key
key = ChaCha20Poly1305.generate_key()
chacha = ChaCha20Poly1305(key)

# Generate nonce
nonce = os.urandom(12)

# Encrypt
plaintext = b"Secret data"
ciphertext = chacha.encrypt(nonce, plaintext, None)

# Decrypt
decrypted = chacha.decrypt(nonce, ciphertext, None)
assert decrypted == plaintext
```

**When to use ChaCha20-Poly1305**:
- Mobile devices (ARM without crypto extensions)
- Software-only encryption
- Need constant-time implementation
- Alternative to AES-GCM

**When to use AES-GCM**:
- x86/x64 processors with AES-NI
- Hardware acceleration available
- Compliance requires FIPS-approved algorithms

#### Deprecated/Insecure Algorithms

**❌ Never use**:
- **DES** (Data Encryption Standard) - 56-bit key, broken
- **3DES** (Triple DES) - 112-bit effective key, deprecated
- **RC4** - Stream cipher, broken
- **Blowfish** - 64-bit block size, vulnerable to birthday attacks

**Key Takeaways**:
- Use **AES-256-GCM** or **ChaCha20-Poly1305**
- Always use authenticated encryption (AEAD)
- Never reuse nonces
- Use hardware acceleration when available

---

## Key Management

### Key Hierarchy

**Principle**: Separate encryption keys from data encryption keys (DEKs).

```
┌──────────────────────────────────────────┐
│ Root Key (Master Key)                    │  ← Stored in HSM or KMS
│ - Rarely changed                         │
│ - Used to encrypt KEKs                   │
└──────────────┬───────────────────────────┘
               │
               ▼
┌──────────────────────────────────────────┐
│ Key Encryption Key (KEK)                 │  ← Encrypted by root key
│ - Changed periodically (e.g., yearly)    │
│ - Used to encrypt DEKs                   │
└──────────────┬───────────────────────────┘
               │
               ▼
┌──────────────────────────────────────────┐
│ Data Encryption Key (DEK)                │  ← Encrypted by KEK
│ - Changed frequently (e.g., daily)       │
│ - Used to encrypt actual data            │
└──────────────┬───────────────────────────┘
               │
               ▼
       ┌──────────────────┐
       │ Encrypted Data   │  ← Encrypted by DEK
       └──────────────────┘
```

**Benefits**:
- **Key rotation**: Rotate KEKs without re-encrypting all data
- **Performance**: Encrypt DEKs (small) instead of data (large)
- **Security**: Compromise of DEK doesn't expose root key

### Key Generation

**Cryptographically Secure Random Number Generators (CSRNGs)**:

| Language | CSRNG Function | Entropy Source |
|----------|---------------|----------------|
| Python | `os.urandom()`, `secrets` | `/dev/urandom` (Linux), CryptGenRandom (Windows) |
| Go | `crypto/rand.Reader` | `/dev/urandom` |
| Node.js | `crypto.randomBytes()` | OpenSSL |
| OpenSSL | `RAND_bytes()` | `/dev/urandom` |

**❌ Never use**:
- `random.random()` (Python) - Predictable
- `Math.random()` (JavaScript) - Predictable
- `rand()` (C) - Predictable
- Timestamp-based keys
- Hardcoded keys

**✅ Good key generation**:
```python
import os
import secrets

# Generate 256-bit key (32 bytes)
key = os.urandom(32)

# Or use secrets module (Python 3.6+)
key = secrets.token_bytes(32)

# Generate key from password (DO NOT use directly, see KDF section)
```

### Key Derivation Functions (KDFs)

**Purpose**: Derive encryption keys from passwords or passphrases.

**Problem**: Passwords are low-entropy, weak keys.
**Solution**: Use KDF to derive strong keys from passwords.

#### PBKDF2 (Password-Based Key Derivation Function 2)

**Standard**: RFC 8018 (PKCS #5)
**Algorithm**: HMAC + iteration count
**Parameters**:
- Password/passphrase
- Salt (16+ bytes, random)
- Iteration count (100,000+ for HMAC-SHA256)
- Key length (32 bytes for AES-256)

**Python Example**:
```python
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os

password = b"user-password"
salt = os.urandom(16)

kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,  # 256 bits
    salt=salt,
    iterations=480000,  # OWASP recommendation (2023)
)

key = kdf.derive(password)
```

**Pros**: FIPS-approved, widely supported
**Cons**: Vulnerable to GPU/ASIC attacks

#### Argon2

**Standard**: RFC 9106 (2021)
**Algorithm**: Memory-hard KDF
**Variants**:
- **Argon2i**: Optimized for resistance to side-channel attacks
- **Argon2d**: Optimized for resistance to GPU attacks
- **Argon2id**: Hybrid (recommended)

**Parameters**:
- Password
- Salt (16+ bytes)
- Time cost (iterations)
- Memory cost (KB)
- Parallelism (threads)

**Python Example**:
```python
from argon2 import PasswordHasher
import os

ph = PasswordHasher(
    time_cost=3,        # Number of iterations
    memory_cost=65536,  # 64 MB
    parallelism=4,      # 4 threads
    hash_len=32,        # 256-bit key
    salt_len=16,
)

password = "user-password"  # Example only - in production, get from secure input
hash_str = ph.hash(password)

# Verify
try:
    ph.verify(hash_str, password)
    print("Password correct")
except:
    print("Password incorrect")
```

**Pros**: Memory-hard (resistant to GPU/ASIC attacks), winner of Password Hashing Competition (2015)
**Cons**: Not FIPS-approved (yet)

#### scrypt

**Standard**: RFC 7914 (2016)
**Algorithm**: Memory-hard KDF
**Parameters**:
- Password
- Salt (16+ bytes)
- N (CPU/memory cost factor, power of 2, e.g., 2^14)
- r (block size, e.g., 8)
- p (parallelization factor, e.g., 1)

**Python Example**:
```python
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
import os

password = b"user-password"
salt = os.urandom(16)

kdf = Scrypt(
    salt=salt,
    length=32,
    n=2**14,  # CPU/memory cost factor
    r=8,      # Block size
    p=1,      # Parallelization factor
)

key = kdf.derive(password)
```

**Pros**: Memory-hard, widely supported
**Cons**: Complex parameter tuning

#### Recommendations

**For password hashing (authentication)**:
- **First choice**: Argon2id
- **FIPS compliance**: PBKDF2-HMAC-SHA256 (480,000+ iterations)
- **Legacy systems**: bcrypt

**For key derivation (encryption)**:
- **First choice**: Argon2id or scrypt
- **FIPS compliance**: PBKDF2-HMAC-SHA256

### Key Storage

**❌ Never store keys**:
- Hardcoded in source code
- In configuration files (plaintext)
- In version control (Git)
- In environment variables (for production)
- In application logs
- In databases (unencrypted)

**✅ Secure key storage**:

#### Option 1: Hardware Security Module (HSM)

**What**: Dedicated hardware for key storage and cryptographic operations.

**Features**:
- Keys never leave HSM
- FIPS 140-2 Level 3/4 certified
- Tamper-resistant
- Expensive ($10K-$100K+)

**Use Case**: High-security environments (banks, government).

**Examples**:
- Thales Luna HSM
- AWS CloudHSM
- Google Cloud HSM
- Azure Dedicated HSM

#### Option 2: Cloud Key Management Service (KMS)

**What**: Managed service for key storage and encryption.

**Features**:
- API-based key management
- Automatic key rotation
- Access control (IAM)
- Audit logging
- Lower cost ($1-$10/month per key)

**Use Case**: Cloud-native applications.

**Examples**:
- AWS KMS
- Google Cloud KMS
- Azure Key Vault
- HashiCorp Vault

#### Option 3: Software-Based Key Management

**What**: Store keys encrypted with master key.

**Pattern**:
1. Generate master key (stored securely, e.g., HSM or KMS)
2. Encrypt data encryption keys (DEKs) with master key
3. Store encrypted DEKs alongside encrypted data

**Example (envelope encryption)**:
```python
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
import json

# Master key (stored in KMS or HSM)
master_key = os.urandom(32)
master_aesgcm = AESGCM(master_key)

# Generate DEK for this data
dek = AESGCM.generate_key(bit_length=256)
dek_nonce = os.urandom(12)

# Encrypt DEK with master key
encrypted_dek = master_aesgcm.encrypt(dek_nonce, dek, None)

# Encrypt data with DEK
data_aesgcm = AESGCM(dek)
data_nonce = os.urandom(12)
plaintext = b"Sensitive data"
ciphertext = data_aesgcm.encrypt(data_nonce, plaintext, None)

# Store encrypted DEK + ciphertext
envelope = {
    "encrypted_dek": encrypted_dek.hex(),
    "dek_nonce": dek_nonce.hex(),
    "ciphertext": ciphertext.hex(),
    "data_nonce": data_nonce.hex(),
}

print(json.dumps(envelope, indent=2))
```

**Decryption**:
```python
# Load envelope
envelope = json.loads(envelope_json)

# Decrypt DEK with master key
dek = master_aesgcm.decrypt(
    bytes.fromhex(envelope["dek_nonce"]),
    bytes.fromhex(envelope["encrypted_dek"]),
    None
)

# Decrypt data with DEK
data_aesgcm = AESGCM(dek)
plaintext = data_aesgcm.decrypt(
    bytes.fromhex(envelope["data_nonce"]),
    bytes.fromhex(envelope["ciphertext"]),
    None
)
```

#### Option 4: Operating System Keystore

**What**: OS-provided secure storage (e.g., macOS Keychain, Windows Credential Manager).

**Use Case**: Desktop applications, local development.

**Python Example (macOS Keychain)**:
```python
import keyring

# Store key
keyring.set_password("myapp", "encryption_key", "base64-encoded-key")

# Retrieve key
key = keyring.get_password("myapp", "encryption_key")
```

### Key Access Control

**Principle of Least Privilege**: Only authorized users/services should access keys.

**AWS KMS Example (IAM Policy)**:
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey"
      ],
      "Resource": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012",
      "Condition": {
        "StringEquals": {
          "kms:EncryptionContext:AppName": "myapp"
        }
      }
    }
  ]
}
```

**Best Practices**:
- Use separate keys for different environments (dev, staging, prod)
- Use separate keys for different applications
- Rotate keys regularly
- Audit key access (CloudTrail, Stackdriver, Azure Monitor)
- Use encryption context for additional security

---

## Envelope Encryption

### Concept

**Problem**: Encrypting large amounts of data with KMS is slow and expensive (API calls).

**Solution**:
1. Generate Data Encryption Key (DEK) locally
2. Encrypt data with DEK (fast, local)
3. Encrypt DEK with KMS (small, one API call)
4. Store encrypted DEK + encrypted data together

**Flow**:
```
┌─────────────┐
│  Plaintext  │
└──────┬──────┘
       │
       ▼
┌─────────────────────────────┐
│ Generate DEK (local)        │
│ key = os.urandom(32)        │
└─────────┬───────────────────┘
          │
          ▼
┌─────────────────────────────┐
│ Encrypt data with DEK       │
│ ciphertext = encrypt(       │
│   plaintext, dek            │
│ )                           │
└─────────┬───────────────────┘
          │
          ▼
┌─────────────────────────────┐
│ Encrypt DEK with KMS        │  ← One API call
│ encrypted_dek = kms.encrypt(│
│   dek                       │
│ )                           │
└─────────┬───────────────────┘
          │
          ▼
┌─────────────────────────────┐
│ Store encrypted_dek +       │
│       ciphertext            │
└─────────────────────────────┘
```

**Decryption**:
```
┌─────────────────────────────┐
│ Load encrypted_dek +        │
│      ciphertext             │
└─────────┬───────────────────┘
          │
          ▼
┌─────────────────────────────┐
│ Decrypt DEK with KMS        │  ← One API call
│ dek = kms.decrypt(          │
│   encrypted_dek             │
│ )                           │
└─────────┬───────────────────┘
          │
          ▼
┌─────────────────────────────┐
│ Decrypt data with DEK       │
│ plaintext = decrypt(        │
│   ciphertext, dek           │
│ )                           │
└─────────┬───────────────────┘
          │
          ▼
┌─────────────┐
│  Plaintext  │
└─────────────┘
```

### AWS KMS Envelope Encryption

**Python Example**:
```python
import boto3
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
import json

kms = boto3.client('kms')
KMS_KEY_ID = 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'

def encrypt_file(plaintext, kms_key_id):
    """Encrypt file using envelope encryption with AWS KMS"""

    # 1. Generate DEK (plaintext key)
    response = kms.generate_data_key(
        KeyId=kms_key_id,
        KeySpec='AES_256'
    )

    dek_plaintext = response['Plaintext']      # DEK (plaintext)
    dek_encrypted = response['CiphertextBlob']  # DEK encrypted by KMS

    # 2. Encrypt data with DEK
    aesgcm = AESGCM(dek_plaintext)
    nonce = os.urandom(12)
    ciphertext = aesgcm.encrypt(nonce, plaintext, None)

    # 3. Return envelope (encrypted DEK + ciphertext)
    return {
        'encrypted_dek': dek_encrypted,
        'ciphertext': ciphertext,
        'nonce': nonce,
    }

def decrypt_file(envelope, kms_key_id):
    """Decrypt file using envelope encryption with AWS KMS"""

    # 1. Decrypt DEK with KMS
    response = kms.decrypt(
        CiphertextBlob=envelope['encrypted_dek']
    )
    dek_plaintext = response['Plaintext']

    # 2. Decrypt data with DEK
    aesgcm = AESGCM(dek_plaintext)
    plaintext = aesgcm.decrypt(
        envelope['nonce'],
        envelope['ciphertext'],
        None
    )

    return plaintext

# Usage
plaintext = b"Sensitive data to encrypt"
envelope = encrypt_file(plaintext, KMS_KEY_ID)
decrypted = decrypt_file(envelope, KMS_KEY_ID)
assert decrypted == plaintext
```

### Google Cloud KMS Envelope Encryption

**Python Example**:
```python
from google.cloud import kms
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

def encrypt_with_gcp_kms(plaintext, project_id, location_id, key_ring_id, key_id):
    """Encrypt using envelope encryption with GCP KMS"""

    # Initialize KMS client
    client = kms.KeyManagementServiceClient()
    key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)

    # 1. Generate DEK locally
    dek = AESGCM.generate_key(bit_length=256)

    # 2. Encrypt data with DEK
    aesgcm = AESGCM(dek)
    nonce = os.urandom(12)
    ciphertext = aesgcm.encrypt(nonce, plaintext, None)

    # 3. Encrypt DEK with KMS
    encrypt_response = client.encrypt(
        request={'name': key_name, 'plaintext': dek}
    )
    encrypted_dek = encrypt_response.ciphertext

    return {
        'encrypted_dek': encrypted_dek,
        'ciphertext': ciphertext,
        'nonce': nonce,
    }

def decrypt_with_gcp_kms(envelope, project_id, location_id, key_ring_id, key_id):
    """Decrypt using envelope encryption with GCP KMS"""

    client = kms.KeyManagementServiceClient()
    key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)

    # 1. Decrypt DEK with KMS
    decrypt_response = client.decrypt(
        request={'name': key_name, 'ciphertext': envelope['encrypted_dek']}
    )
    dek = decrypt_response.plaintext

    # 2. Decrypt data with DEK
    aesgcm = AESGCM(dek)
    plaintext = aesgcm.decrypt(
        envelope['nonce'],
        envelope['ciphertext'],
        None
    )

    return plaintext
```

### Benefits of Envelope Encryption

1. **Performance**: Local encryption (fast) + one KMS call (small overhead)
2. **Cost**: Fewer KMS API calls
3. **Scalability**: Can encrypt large files without KMS payload limits
4. **Key rotation**: Rotate master key without re-encrypting data (just re-encrypt DEKs)

---

## Database Encryption

### Transparent Data Encryption (TDE)

**What**: Database-level encryption that encrypts entire database files.

**How it works**:
1. Database generates master key
2. Database encrypts data pages before writing to disk
3. Database decrypts data pages after reading from disk
4. Applications see plaintext (transparent)

**Pros**:
- No application changes required
- Encrypts all data (tables, indexes, logs)
- Protects backups
- Minimal performance overhead (~3-10%)

**Cons**:
- Database has full access to keys
- All-or-nothing (can't encrypt specific columns)
- Doesn't protect against application-level attacks

### PostgreSQL TDE

**Status**: Not natively supported (as of PostgreSQL 16).

**Alternatives**:
1. **pgcrypto extension**: Column-level encryption
2. **Filesystem-level encryption**: LUKS, dm-crypt
3. **Cloud provider TDE**: AWS RDS, Google Cloud SQL

**pgcrypto Example (Column-Level Encryption)**:
```sql
-- Enable pgcrypto extension
CREATE EXTENSION pgcrypto;

-- Encrypt data
INSERT INTO users (email, encrypted_ssn)
VALUES (
    'user@example.com',
    pgp_sym_encrypt('123-45-6789', 'encryption-password')
);

-- Decrypt data
SELECT
    email,
    pgp_sym_decrypt(encrypted_ssn::bytea, 'encryption-password') AS ssn
FROM users;
```

**Best Practice**: Use envelope encryption with KMS instead of hardcoded password:
```sql
-- Store encrypted DEK alongside data
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255),
    encrypted_ssn BYTEA,
    encrypted_dek BYTEA,  -- DEK encrypted by KMS
    dek_nonce BYTEA
);

-- Application encrypts SSN with DEK, encrypts DEK with KMS
-- Store both encrypted_ssn and encrypted_dek
```

### MySQL TDE

**Support**: MySQL 5.7+ (Enterprise), MariaDB 10.1+

**Setup**:
```sql
-- Enable TDE plugin
INSTALL PLUGIN keyring_file SONAME 'keyring_file.so';

-- Configure keyring in my.cnf
[mysqld]
early-plugin-load=keyring_file.so
keyring_file_data=/var/lib/mysql-keyring/keyring

-- Create encrypted table
CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(255),
    ssn VARCHAR(11)
) ENCRYPTION='Y';

-- Encrypt existing table
ALTER TABLE users ENCRYPTION='Y';
```

**Key Rotation**:
```sql
-- Rotate master key
ALTER INSTANCE ROTATE INNODB MASTER KEY;
```

### MongoDB Encryption at Rest

**Support**: MongoDB 3.2+ (Enterprise, Atlas)

**Configuration** (mongod.conf):
```yaml
security:
  enableEncryption: true
  encryptionKeyFile: /etc/mongodb-keyfile

# Or use KMIP (Key Management Interoperability Protocol)
security:
  enableEncryption: true
  kmip:
    serverName: kmip.example.com
    port: 5696
    clientCertificateFile: /etc/mongodb-client.pem
```

**Encrypted Storage Engine**:
- Uses AES-256-CBC
- Encrypts data files, journals, logs
- Keys stored in keyfile or KMIP server
- Automatic decryption on read

**Encrypted Collections** (Client-Side Field Level Encryption - CSFLE):
```javascript
const { ClientEncryption } = require('mongodb-client-encryption');

// Setup encryption options
const encryptionOptions = {
  keyVaultNamespace: 'encryption.__keyVault',
  kmsProviders: {
    aws: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    }
  }
};

// Create encrypted client
const client = new MongoClient(uri, {
  autoEncryption: encryptionOptions
});

// Create data key
const encryption = new ClientEncryption(client, encryptionOptions);
const dataKeyId = await encryption.createDataKey('aws', {
  masterKey: {
    key: 'arn:aws:kms:us-east-1:123456789012:key/12345678',
    region: 'us-east-1'
  }
});

// Create collection with encrypted fields
await db.createCollection('users', {
  validator: {
    $jsonSchema: {
      properties: {
        ssn: {
          encrypt: {
            keyId: [dataKeyId],
            algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
          }
        }
      }
    }
  }
});

// Insert encrypted data (automatic)
await db.collection('users').insertOne({
  name: 'John Doe',
  ssn: '123-45-6789'  // Automatically encrypted
});
```

### SQLite Encryption

**Native**: SQLite doesn't support encryption natively.

**Extensions**:
1. **SQLCipher**: Open-source SQLite extension
2. **SEE (SQLite Encryption Extension)**: Commercial

**SQLCipher Setup (Python)**:
```python
from pysqlcipher3 import dbapi2 as sqlite3

# Connect to encrypted database
conn = sqlite3.connect('encrypted.db')
conn.execute("PRAGMA key='strong-password'")

# Set encryption algorithm
conn.execute("PRAGMA cipher='aes-256-cbc'")

# Create table and insert data
conn.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)')
conn.execute("INSERT INTO users (email) VALUES ('user@example.com')")
conn.commit()
```

**Key Derivation**: SQLCipher uses PBKDF2-HMAC-SHA512 by default.

**Rekey** (change password):
```python
conn.execute("PRAGMA rekey='new-strong-password'")
```

---

## File and Disk Encryption

### Linux: LUKS (Linux Unified Key Setup)

**What**: Standard disk encryption on Linux.

**Features**:
- Full-disk or partition encryption
- Multiple key slots (up to 8 passphrases/keys)
- Uses dm-crypt kernel module
- Supports AES, XTS mode

**Setup**:
```bash
# Format partition with LUKS
sudo cryptsetup luksFormat /dev/sdb1

# Open encrypted partition
sudo cryptsetup luksOpen /dev/sdb1 encrypted_disk

# Create filesystem
sudo mkfs.ext4 /dev/mapper/encrypted_disk

# Mount
sudo mount /dev/mapper/encrypted_disk /mnt/encrypted

# Auto-mount on boot (add to /etc/crypttab)
echo "encrypted_disk /dev/sdb1 none luks" | sudo tee -a /etc/crypttab

# Add to /etc/fstab
echo "/dev/mapper/encrypted_disk /mnt/encrypted ext4 defaults 0 2" | sudo tee -a /etc/fstab
```

**Key Management**:
```bash
# Add new key slot
sudo cryptsetup luksAddKey /dev/sdb1

# Remove key slot
sudo cryptsetup luksRemoveKey /dev/sdb1

# Backup LUKS header
sudo cryptsetup luksHeaderBackup /dev/sdb1 --header-backup-file luks-header-backup

# Restore LUKS header
sudo cryptsetup luksHeaderRestore /dev/sdb1 --header-backup-file luks-header-backup
```

**Key File** (instead of passphrase):
```bash
# Generate key file
dd if=/dev/urandom of=/root/keyfile bs=1024 count=4
chmod 600 /root/keyfile

# Add key file to LUKS
sudo cryptsetup luksAddKey /dev/sdb1 /root/keyfile

# Open with key file
sudo cryptsetup luksOpen /dev/sdb1 encrypted_disk --key-file /root/keyfile
```

### eCryptfs (Enterprise Cryptographic Filesystem)

**What**: Stacked filesystem encryption (per-directory).

**Use Case**: Encrypt user home directories.

**Setup**:
```bash
# Install eCryptfs
sudo apt-get install ecryptfs-utils

# Setup encrypted directory
mkdir ~/Private
sudo mount -t ecryptfs ~/Private ~/Private

# Configure encryption options (interactive)
# - Key type: passphrase
# - Cipher: aes
# - Key bytes: 32 (AES-256)
# - Plaintext passthrough: no
# - Filename encryption: yes

# Add to /etc/fstab for auto-mount
/home/user/Private /home/user/Private ecryptfs defaults 0 0
```

**Encrypting Home Directory**:
```bash
# Migrate existing home directory to encrypted
ecryptfs-migrate-home -u username
```

### Windows: BitLocker

**What**: Full-disk encryption on Windows (Pro/Enterprise).

**Setup** (via GUI):
1. Control Panel → BitLocker Drive Encryption
2. Turn on BitLocker for drive
3. Choose authentication method (password, smart card, TPM)
4. Save recovery key
5. Encrypt drive

**Setup** (via PowerShell):
```powershell
# Enable BitLocker with password
Enable-BitLocker -MountPoint "C:" -PasswordProtector -Password (ConvertTo-SecureString "password" -AsPlainText -Force)

# Backup recovery key
Backup-BitLockerKeyProtector -MountPoint "C:" -KeyProtectorId (Get-BitLockerVolume -MountPoint "C:").KeyProtector[0].KeyProtectorId -Path "C:\recovery-key.txt"

# Encrypt drive
Resume-BitLocker -MountPoint "C:"
```

**TPM (Trusted Platform Module)**: Hardware chip that stores encryption keys.

**Recovery Key**: 48-digit recovery password, stored in Active Directory or printed.

### macOS: FileVault 2

**What**: Full-disk encryption on macOS.

**Setup** (via GUI):
1. System Preferences → Security & Privacy → FileVault
2. Turn On FileVault
3. Choose recovery method (iCloud or recovery key)
4. Restart to encrypt

**Setup** (via command line):
```bash
# Enable FileVault
sudo fdesetup enable

# Check status
sudo fdesetup status

# List enabled users
sudo fdesetup list
```

**Recovery Key**: 24-character alphanumeric key, store securely.

### File-Level Encryption (GPG)

**What**: Encrypt individual files with GPG (GNU Privacy Guard).

**Setup**:
```bash
# Generate GPG key pair
gpg --full-generate-key

# Encrypt file
gpg --encrypt --recipient user@example.com file.txt

# Decrypt file
gpg --decrypt file.txt.gpg > file.txt
```

**Symmetric Encryption** (password-based):
```bash
# Encrypt
gpg --symmetric --cipher-algo AES256 file.txt

# Decrypt
gpg --decrypt file.txt.gpg > file.txt
```

---

## Cloud KMS Integration

### AWS KMS

**Features**:
- Managed key storage
- FIPS 140-2 Level 2 validated
- Automatic key rotation (annual)
- Audit logging (CloudTrail)
- Integration with AWS services (S3, EBS, RDS)

**Setup**:
```bash
# Create KMS key
aws kms create-key --description "My encryption key"

# Create alias
aws kms create-alias --alias-name alias/my-key --target-key-id 12345678-1234-1234-1234-123456789012

# Enable automatic key rotation
aws kms enable-key-rotation --key-id 12345678-1234-1234-1234-123456789012
```

**Python SDK**:
```python
import boto3

kms = boto3.client('kms')

# Encrypt data directly (max 4 KB)
response = kms.encrypt(
    KeyId='alias/my-key',
    Plaintext=b'Secret data',
    EncryptionContext={'Department': 'Finance'}
)
ciphertext = response['CiphertextBlob']

# Decrypt
response = kms.decrypt(
    CiphertextBlob=ciphertext,
    EncryptionContext={'Department': 'Finance'}
)
plaintext = response['Plaintext']

# Generate data key (for envelope encryption)
response = kms.generate_data_key(
    KeyId='alias/my-key',
    KeySpec='AES_256'
)
dek_plaintext = response['Plaintext']
dek_encrypted = response['CiphertextBlob']
```

**Encryption Context**: Additional authenticated data (AAD) for additional security.

**Key Policies** (IAM-like permissions for keys):
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow use of the key for encryption",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/MyAppRole"
      },
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey",
        "kms:GenerateDataKey"
      ],
      "Resource": "*"
    }
  ]
}
```

### Google Cloud KMS

**Features**:
- Managed key storage
- FIPS 140-2 Level 3 validated (HSM option)
- Automatic key rotation (configurable)
- Audit logging (Cloud Audit Logs)
- Integration with GCP services (GCS, GCE, BigQuery)

**Setup**:
```bash
# Create key ring
gcloud kms keyrings create my-keyring --location us-east1

# Create key
gcloud kms keys create my-key \
  --location us-east1 \
  --keyring my-keyring \
  --purpose encryption

# Enable automatic rotation (90 days)
gcloud kms keys update my-key \
  --location us-east1 \
  --keyring my-keyring \
  --rotation-period 90d \
  --next-rotation-time 2025-12-01T00:00:00Z
```

**Python SDK**:
```python
from google.cloud import kms

client = kms.KeyManagementServiceClient()

# Key resource name
key_name = 'projects/my-project/locations/us-east1/keyRings/my-keyring/cryptoKeys/my-key'

# Encrypt
plaintext = b'Secret data'
encrypt_response = client.encrypt(
    request={'name': key_name, 'plaintext': plaintext}
)
ciphertext = encrypt_response.ciphertext

# Decrypt
decrypt_response = client.decrypt(
    request={'name': key_name, 'ciphertext': ciphertext}
)
plaintext = decrypt_response.plaintext
```

**IAM Permissions**:
```bash
# Grant encrypt/decrypt permissions
gcloud kms keys add-iam-policy-binding my-key \
  --location us-east1 \
  --keyring my-keyring \
  --member serviceAccount:my-app@my-project.iam.gserviceaccount.com \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter
```

### Azure Key Vault

**Features**:
- Managed key storage
- FIPS 140-2 Level 2 validated (Premium: HSM)
- Automatic key rotation (configurable)
- Audit logging (Azure Monitor)
- Integration with Azure services (Storage, SQL, VMs)

**Setup**:
```bash
# Create Key Vault
az keyvault create \
  --name my-keyvault \
  --resource-group my-rg \
  --location eastus

# Create key
az keyvault key create \
  --vault-name my-keyvault \
  --name my-key \
  --protection software \
  --kty RSA \
  --size 2048

# Enable automatic rotation
az keyvault key rotation-policy update \
  --vault-name my-keyvault \
  --name my-key \
  --value '{"lifetimeActions":[{"trigger":{"timeAfterCreate":"P90D"},"action":{"type":"Rotate"}}],"attributes":{"expiryTime":"P2Y"}}'
```

**Python SDK**:
```python
from azure.identity import DefaultAzureCredential
from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm

credential = DefaultAzureCredential()
key_url = "https://my-keyvault.vault.azure.net/keys/my-key"

crypto_client = CryptographyClient(key_url, credential)

# Encrypt
plaintext = b"Secret data"
result = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep, plaintext)
ciphertext = result.ciphertext

# Decrypt
result = crypto_client.decrypt(EncryptionAlgorithm.rsa_oaep, ciphertext)
plaintext = result.plaintext
```

**Access Policies**:
```bash
# Grant permissions to application
az keyvault set-policy \
  --name my-keyvault \
  --object-id <app-object-id> \
  --key-permissions encrypt decrypt get list
```

### HashiCorp Vault

**What**: Open-source secrets management and encryption service.

**Features**:
- Encryption as a Service (Transit Secrets Engine)
- Dynamic secrets
- Secrets versioning
- Audit logging
- Self-hosted or managed (HCP Vault)

**Setup**:
```bash
# Start Vault dev server (testing only)
vault server -dev

# Set VAULT_ADDR
export VAULT_ADDR='http://127.0.0.1:8200'

# Enable Transit secrets engine
vault secrets enable transit

# Create encryption key
vault write -f transit/keys/my-key
```

**Encrypt/Decrypt**:
```bash
# Encrypt
vault write transit/encrypt/my-key plaintext=$(echo "Secret data" | base64)

# Output:
# Key           Value
# ciphertext    vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM96F4qzA==

# Decrypt
vault write transit/decrypt/my-key ciphertext="vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM96F4qzA=="

# Output (base64 encoded):
# plaintext     U2VjcmV0IGRhdGE=

# Decode
echo "U2VjcmV0IGRhdGE=" | base64 -d
# Output: Secret data
```

**Python SDK (hvac)**:
```python
import hvac
import base64

client = hvac.Client(url='http://127.0.0.1:8200', token='dev-token')

# Encrypt
plaintext = b'Secret data'
response = client.secrets.transit.encrypt_data(
    name='my-key',
    plaintext=base64.b64encode(plaintext).decode('utf-8')
)
ciphertext = response['data']['ciphertext']

# Decrypt
response = client.secrets.transit.decrypt_data(
    name='my-key',
    ciphertext=ciphertext
)
plaintext = base64.b64decode(response['data']['plaintext'])
```

**Key Rotation**:
```bash
# Rotate key (creates new version)
vault write -f transit/keys/my-key/rotate

# Re-encrypt data with new key version
vault write transit/rewrap/my-key ciphertext="vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM96F4qzA=="
```

---

## Key Rotation

### Why Rotate Keys?

**Reasons**:
1. **Limit blast radius**: Compromise of old key doesn't affect new data
2. **Compliance**: Many standards require periodic rotation (e.g., PCI-DSS)
3. **Cryptographic hygiene**: Reduce ciphertext exposure
4. **Mitigate key exposure**: Employee departure, system compromise

**How Often?**:
- **Master keys**: Annually
- **Data encryption keys (DEKs)**: Monthly or per dataset
- **Secrets (passwords, API keys)**: 90 days
- **Emergency rotation**: Immediately on suspected compromise

### Rotation Strategies

#### Strategy 1: Re-encrypt All Data (Complete Rotation)

**How**:
1. Generate new key
2. Decrypt all data with old key
3. Encrypt all data with new key
4. Update key references
5. Delete old key (after grace period)

**Pros**: Clean, simple
**Cons**: Expensive (re-encrypt all data), downtime, risky

**Use Case**: Small datasets, infrequent rotation.

**Example**:
```python
def rotate_complete(old_key, new_key, data_files):
    for file_path in data_files:
        # Read encrypted data
        with open(file_path, 'rb') as f:
            ciphertext = f.read()

        # Decrypt with old key
        plaintext = decrypt(ciphertext, old_key)

        # Encrypt with new key
        new_ciphertext = encrypt(plaintext, new_key)

        # Write back
        with open(file_path, 'wb') as f:
            f.write(new_ciphertext)
```

#### Strategy 2: Envelope Encryption (Zero-Downtime Rotation)

**How** (using key hierarchy):
1. Generate new KEK (Key Encryption Key)
2. Re-encrypt all DEKs with new KEK
3. Data stays encrypted with DEKs (no change)
4. Update KEK references
5. Delete old KEK

**Pros**: Fast (only re-encrypt DEKs, not data), no downtime
**Cons**: Requires key hierarchy

**Use Case**: Large datasets, cloud KMS.

**Flow**:
```
Before Rotation:
┌────────────────┐
│  Old KEK       │
└───────┬────────┘
        │
        ▼
┌───────────────

…(truncated)
