cryptography-encryption-at-rest

Protecting stored data with encryption at rest

Encryption at Rest

Scope: Data encryption, key management, compliance (FIPS, PCI-DSS, HIPAA) Lines: ~350 Last Updated: 2025-10-27

When to Use This Skill

Activate this skill when:

Core Concepts

What is Encryption at Rest?

Encryption at rest protects data stored on disk from unauthorized access when the data is not actively being transmitted.

Threat model:

Encryption Layers

┌─────────────────────────────────────────┐
│ Application-Level (field encryption)    │ ← Highest control, most complex
├─────────────────────────────────────────┤
│ Database-Level (TDE)                    │ ← Transparent, good performance
├─────────────────────────────────────────┤
│ Filesystem-Level                        │ ← Per-directory encryption
├─────────────────────────────────────────┤
│ Volume/Block-Level (LUKS, BitLocker)    │ ← Full disk encryption
├─────────────────────────────────────────┤
│ Hardware-Level (self-encrypting drives) │ ← Fastest, lowest control
└─────────────────────────────────────────┘

Trade-offs:


Key Management Patterns

1. Envelope Encryption (Recommended)

Pattern: Encrypt data with Data Encryption Key (DEK), encrypt DEK with Key Encryption Key (KEK).

┌──────────────┐
│ KMS (KEK)    │ ← Master key in secure KMS
└──────┬───────┘
       │ encrypts
┌──────▼───────┐
│ DEK          │ ← Data Encryption Key (one per file/object)
└──────┬───────┘
       │ encrypts
┌──────▼───────┐
│ Data         │ ← Actual data
└──────────────┘

Benefits:

Example:

# Generate DEK from KMS
plaintext_dek, encrypted_dek = kms.generate_data_key()

# Encrypt data with DEK (local, fast)
ciphertext = encrypt(data, plaintext_dek)

# Store encrypted_dek alongside ciphertext
save(ciphertext, encrypted_dek)

# Decrypt: decrypt DEK with KMS, then decrypt data
plaintext_dek = kms.decrypt(encrypted_dek)
data = decrypt(ciphertext, plaintext_dek)

2. Direct KMS Encryption

Pattern: Encrypt data directly using KMS.

Use case: Small data (<4KB), secrets, API keys.

Limitations:

3. Password-Based Encryption

Pattern: Derive key from password using Key Derivation Function (KDF).

# Derive key from password
key = pbkdf2(password, salt, iterations=100000)

# Encrypt with derived key
ciphertext = encrypt(data, key)

Use case: User-encrypted files, backup encryption.

Critical: Use strong KDF (PBKDF2, Argon2, scrypt) with high iterations.


Algorithms

Recommended Algorithms

Symmetric encryption (for bulk data):

Avoid:

Key sizes:

Hardware Acceleration

AES-NI: Intel/AMD instruction set for AES encryption.

# Check if AES-NI is available
grep -q aes /proc/cpuinfo && echo "AES-NI supported" || echo "No AES-NI"

Performance impact:

Recommendation: Use ChaCha20-Poly1305 if AES-NI unavailable.


Database Encryption

PostgreSQL

Option 1: Application-level (recommended)

# Encrypt before INSERT
encrypted = encrypt(plaintext, key)
cursor.execute("INSERT INTO users (ssn) VALUES (%s)", (encrypted,))

Option 2: pgcrypto extension

CREATE EXTENSION pgcrypto;

-- Encrypt column
UPDATE users SET ssn_encrypted = pgp_sym_encrypt(ssn, 'key');

-- Decrypt column
SELECT pgp_sym_decrypt(ssn_encrypted, 'key') FROM users;

Option 3: Filesystem encryption (LUKS)

# Encrypt PostgreSQL data directory with LUKS
cryptsetup luksFormat /dev/sdb1
cryptsetup luksOpen /dev/sdb1 postgres_data
mount /dev/mapper/postgres_data /var/lib/postgresql/data

MongoDB

Native encryption (Enterprise):

# mongod.conf
security:
  enableEncryption: true
  encryptionKeyFile: /path/to/keyfile

Client-Side Field Level Encryption (CSFLE):

// Encrypt specific fields before storing
const autoEncryptionOpts = {
  kmsProviders: { aws: { ... } },
  schemaMap: {
    'db.collection': {
      properties: {
        ssn: { encrypt: { algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Random' } }
      }
    }
  }
};

const client = new MongoClient(uri, { autoEncryption: autoEncryptionOpts });

MySQL

InnoDB encryption:

-- Enable encryption for table
CREATE TABLE users (
  id INT PRIMARY KEY,
  ssn VARCHAR(20)
) ENCRYPTION='Y';

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

File and Disk Encryption

Linux: LUKS (dm-crypt)

# Create encrypted volume
cryptsetup luksFormat /dev/sdb1

# Open encrypted volume
cryptsetup luksOpen /dev/sdb1 encrypted_volume

# Mount
mount /dev/mapper/encrypted_volume /mnt/encrypted

# Auto-mount on boot (/etc/crypttab)
encrypted_volume /dev/sdb1 none luks

Algorithms: AES-256-XTS (default), ChaCha20

macOS: FileVault

# Enable FileVault (GUI or CLI)
sudo fdesetup enable

# Check status
fdesetup status

Windows: BitLocker

# Enable BitLocker
Enable-BitLocker -MountPoint "C:" -EncryptionMethod Aes256 -UsedSpaceOnly

# Check status
Get-BitLockerVolume

Cloud KMS Integration

AWS KMS

import boto3

kms = boto3.client('kms', region_name='us-east-1')

# Generate data key (envelope encryption)
response = kms.generate_data_key(
    KeyId='alias/my-app-key',
    KeySpec='AES_256'
)

plaintext_key = response['Plaintext']
encrypted_key = response['CiphertextBlob']

# Encrypt data locally with plaintext_key
# Store encrypted_key alongside encrypted data

# Decrypt data key
decrypted_key = kms.decrypt(CiphertextBlob=encrypted_key)['Plaintext']

Best practices:

Azure Key Vault

from azure.identity import DefaultAzureCredential
from azure.keyvault.keys.crypto import CryptographyClient

credential = DefaultAzureCredential()
key_client = KeyClient(vault_url="https://myvault.vault.azure.net", credential=credential)

# Get key
key = key_client.get_key("my-encryption-key")

# Encrypt
crypto_client = CryptographyClient(key, credential=credential)
result = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep, plaintext)

external secret manager

# Enable transit secrets engine
vault secrets enable transit

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

# Encrypt data
vault write transit/encrypt/my-app-key plaintext=$(base64 <<< "sensitive data")

# Decrypt data
vault write transit/decrypt/my-app-key ciphertext="vault:v1:..."

Key Rotation

Why rotate keys?

Zero-Downtime Rotation

Phase 1: Dual-key period

1. Generate new key (version 2)
2. Application can decrypt with v1 or v2
3. Application encrypts new data with v2

Phase 2: Migration

4. Background job re-encrypts old data (v1 → v2)
5. Track progress, allow rollback

Phase 3: Deprecate old key

6. Once all data migrated, deprecate v1
7. Keep v1 for emergency rollback (90 days)
8. Retire v1 after retention period

Example:

# Phase 1: Generate new key
new_key = kms.create_key()

# Phase 2: Re-encrypt in batches
for batch in get_encrypted_items(old_key_version, batch_size=1000):
    plaintext = decrypt(batch, old_key)
    ciphertext = encrypt(plaintext, new_key)
    update_item(batch.id, ciphertext, new_key_version)

# Phase 3: Deprecate old key
kms.disable_key(old_key_id)

Compliance

FIPS 140-2

Requirements:

FIPS-approved algorithms:

PCI-DSS

Requirements:

HIPAA

Requirements:

GDPR

Requirements:


Performance Optimization

Benchmarks (AES-256-GCM with AES-NI):

Tips:


Common Pitfalls

Hardcoded keys in code - Exposed in version control ✅ Use KMS or environment variables

Using weak algorithms (DES, 3DES, ECB mode) ✅ Use AES-256-GCM or ChaCha20-Poly1305

No key rotation - Key compromise affects all historical data ✅ Rotate keys quarterly or annually

Storing keys with encrypted data - No protection if both stolen ✅ Store keys in separate KMS

Encrypting with random key and losing it - Permanent data loss ✅ Use KMS, backup keys securely

Not testing decryption - Discover data loss too late ✅ Verify decryption works immediately after encryption


Related Skills


Level 3: Resources

Location: ~/.hanzo/skills/cryptography/encryption-at-rest/resources/

This skill includes comprehensive Level 3 resources for production encryption implementations:

REFERENCE.md (~2,900 lines)

Comprehensive technical reference covering:

Scripts (3 production-ready tools)

validate_encryption.py (504 lines) - Encryption configuration validator

rotate_keys.py (569 lines) - Automated key rotation tool

benchmark_encryption.sh (570 lines) - Encryption performance benchmarking

Examples (7 production-ready implementations)

python/file_encryption.py - File encryption with envelope encryption

python/database_encryption.py - SQLAlchemy field-level encryption

python/aws_kms_integration.py - AWS KMS integration

go/disk_encryption.go - Block-level encryption (AES-XTS)

config/postgres-encryption.conf - PostgreSQL encryption setup

config/mongodb-encryption.conf - MongoDB encryption setup

python/key_rotation.py - Zero-downtime key rotation

Quick Start

# Validate encryption configuration
cd ~/.hanzo/skills/cryptography/encryption-at-rest/resources/scripts
./validate_encryption.py --config-file /etc/app/db.conf --check-compliance PCI-DSS

# Benchmark encryption performance
./benchmark_encryption.sh --all-algorithms --file-size 100M --json

# Rotate encryption keys
./rotate_keys.py --kms-backend local --key-file master.key --data-dir ./data

# Run Python examples
cd ../examples/python
pip install cryptography sqlalchemy boto3
python file_encryption.py
python database_encryption.py
python key_rotation.py

# View comprehensive reference
cd ../
less REFERENCE.md

Integration Notes

CI/CD Integration:

# .github/workflows/security.yml
- name: Validate Encryption
  run: |
    ./scripts/validate_encryption.py \
      --scan-directory ./config \
      --check-compliance FIPS \
      --json \
      --fail-on high

Monitoring:


Quick Reference

# Check for AES-NI hardware acceleration
grep -q aes /proc/cpuinfo && echo "AES-NI available"

# Encrypt file with OpenSSL
openssl enc -aes-256-gcm -in plaintext.txt -out encrypted.bin -K $(openssl rand -hex 32) -iv $(openssl rand -hex 12)

# Generate encryption key (256-bit)
openssl rand -base64 32

# Benchmark encryption speed
openssl speed aes-256-gcm

# Create encrypted LUKS volume
cryptsetup luksFormat /dev/sdb1
cryptsetup luksOpen /dev/sdb1 encrypted_volume

# Enable BitLocker (Windows)
Enable-BitLocker -MountPoint "C:" -EncryptionMethod Aes256

# Check MongoDB encryption status
use admin
db.serverStatus().encryptionAtRest