Data Encryption at Rest: Complete Implementation Guide

Introduction

Data encryption at rest is a fundamental security control that protects stored data from unauthorized access in the event of physical theft, unauthorized system access, or improper disposal of storage media. In today's regulatory environment, with frameworks like GDPR, HIPAA, PCI-DSS, and SOC 2 mandating strong data protection measures, encryption at rest has evolved from a best practice to a compliance requirement for organizations handling sensitive information.

This comprehensive guide provides Linux system administrators with practical, in-depth knowledge of implementing encryption at rest across various storage layers—from full disk encryption to database-level encryption, file system encryption, and application-level encryption. Whether you're protecting customer data, financial information, healthcare records, or intellectual property, this guide covers the technical implementations, key management strategies, and operational procedures necessary to secure data at rest effectively.

Why Data Encryption at Rest Matters

Traditional perimeter security—firewalls, intrusion detection systems, and access controls—cannot protect data once an attacker bypasses these defenses or when storage media is physically compromised. Encryption at rest ensures that even if an attacker gains access to storage devices, backup tapes, or database files, the data remains cryptographically protected and unusable without the proper encryption keys.

Common Threat Scenarios Mitigated by Encryption at Rest:

  1. Physical Device Theft: Laptops, servers, or backup drives stolen from data centers, offices, or during transport
  2. Insider Threats: Malicious or negligent employees with physical access to storage systems
  3. Improper Disposal: Hard drives, SSDs, or backup media discarded without secure wiping
  4. Cloud Storage Breaches: Unauthorized access to cloud storage buckets or volumes
  5. Database File Exposure: Direct access to database files bypassing application-level access controls
  6. Backup Media Compromise: Lost or stolen backup tapes, external drives, or cloud backup credentials
  7. Forensic Analysis: Protection against forensic examination of seized equipment

Encryption at Rest vs. Encryption in Transit

It's critical to understand that encryption at rest and encryption in transit serve different purposes and must both be implemented for comprehensive data protection:

  • Encryption at Rest: Protects data stored on disk, in databases, or in backups when the system is powered off or when files are not actively being accessed
  • Encryption in Transit: Protects data as it moves across networks using protocols like TLS/SSL, SSH, or VPNs

A complete security strategy requires both. This guide focuses exclusively on encryption at rest.

Encryption Approaches Overview

There are multiple layers where encryption at rest can be implemented, each with different use cases, performance implications, and management requirements:

  1. Full Disk Encryption (FDE): Encrypts entire disk partitions or volumes at the block level
  2. File System Encryption: Encrypts individual files or directories within a file system
  3. Database Encryption: Built-in encryption features provided by database management systems
  4. Application-Level Encryption: Encryption implemented within applications before data is written to storage
  5. Hardware-Based Encryption: Self-encrypting drives (SEDs) that handle encryption at the hardware level

This guide covers all these approaches with practical implementation examples for Linux systems.

Understanding Encryption Technologies

Encryption Algorithms and Standards

Modern encryption at rest primarily uses symmetric encryption algorithms due to their performance characteristics:

AES (Advanced Encryption Standard)

  • Most widely used symmetric encryption algorithm
  • Key sizes: 128-bit, 192-bit, 256-bit (AES-256 recommended for sensitive data)
  • NIST-approved standard (FIPS 140-2 compliant)
  • Excellent performance with hardware acceleration (AES-NI)
  • Used in: LUKS, dm-crypt, BitLocker, FileVault, most database encryption

Modes of Operation

  • AES-CBC (Cipher Block Chaining): Traditional mode, requires IV management
  • AES-XTS: Designed specifically for disk encryption, IEEE standard
  • AES-GCM (Galois/Counter Mode): Provides both encryption and authentication

Other Algorithms

  • Blowfish/Twofish: Legacy algorithms, less commonly used today
  • ChaCha20: Modern stream cipher, good for systems without AES-NI
  • Serpent: Alternative to AES, considered highly secure but slower

Key Management Fundamentals

The security of encrypted data ultimately depends on proper key management. Compromised encryption keys render encryption useless.

Key Management Principles:

  1. Key Generation: Use cryptographically secure random number generators
  2. Key Storage: Store keys separately from encrypted data
  3. Key Rotation: Periodically change encryption keys
  4. Key Backup: Securely backup keys to prevent data loss
  5. Key Destruction: Securely destroy old keys when no longer needed
  6. Access Control: Restrict key access to authorized systems/personnel only

Key Storage Options:

  • Hardware Security Modules (HSM): Dedicated hardware for key storage and cryptographic operations
  • Key Management Services (KMS): Cloud-based key management (AWS KMS, Azure Key Vault, Google Cloud KMS)
  • TPM (Trusted Platform Module): Hardware chip for storing encryption keys on endpoints
  • File-Based Keys: Keys stored in protected files (requires careful permission management)
  • Passphrase-Based Keys: Keys derived from user passphrases using KDFs

Full Disk Encryption with LUKS

LUKS (Linux Unified Key Setup) is the standard for disk encryption on Linux systems, providing a platform-independent format specification and comprehensive key management.

Installing LUKS

# Install cryptsetup (LUKS implementation)
sudo apt-get update
sudo apt-get install -y cryptsetup cryptsetup-bin # Debian/Ubuntu
sudo yum install -y cryptsetup-luks # RHEL/CentOS

# Verify installation
cryptsetup --version

Creating Encrypted Partitions

Important: Encrypting a partition destroys all existing data. Always backup first.

# Identify the target partition or disk
lsblk -f
sudo fdisk -l

# Create LUKS encrypted partition
# WARNING: This will erase all data on /dev/sdb1
sudo cryptsetup luksFormat /dev/sdb1

# You will be prompted to confirm and set a passphrase
# Choose a strong passphrase (minimum 20 characters recommended)

# Verify LUKS header
sudo cryptsetup luksDump /dev/sdb1

Opening and Using Encrypted Volumes

# Open the encrypted partition
sudo cryptsetup luksOpen /dev/sdb1 encrypted_volume

# The decrypted volume is now available at /dev/mapper/encrypted_volume

# Create a file system on the encrypted volume
sudo mkfs.ext4 /dev/mapper/encrypted_volume

# Create mount point and mount
sudo mkdir -p /mnt/encrypted
sudo mount /dev/mapper/encrypted_volume /mnt/encrypted

# Verify mount
df -h | grep encrypted

# Use the encrypted volume normally
sudo chown -R user:user /mnt/encrypted
echo "Sensitive data" | sudo tee /mnt/encrypted/test.txt

# Unmount and close when done
sudo umount /mnt/encrypted
sudo cryptsetup luksClose encrypted_volume

Automatic Mounting with Key Files

For servers that need automatic mounting without user interaction, use key files instead of passphrases:

# Generate a random key file
sudo dd if=/dev/urandom of=/root/luks-keys/data-volume.key bs=4096 count=1

# Secure the key file
sudo chmod 400 /root/luks-keys/data-volume.key
sudo chown root:root /root/luks-keys/data-volume.key

# Add key file to LUKS header (allows multiple keys)
sudo cryptsetup luksAddKey /dev/sdb1 /root/luks-keys/data-volume.key

# Verify key slots
sudo cryptsetup luksDump /dev/sdb1 | grep "Key Slot"

# Test opening with key file
sudo cryptsetup luksOpen /dev/sdb1 encrypted_volume --key-file=/root/luks-keys/data-volume.key

# Configure automatic mounting via /etc/crypttab
echo "encrypted_volume /dev/sdb1 /root/luks-keys/data-volume.key luks" | sudo tee -a /etc/crypttab

# Configure mount point in /etc/fstab
echo "/dev/mapper/encrypted_volume /mnt/encrypted ext4 defaults 0 2" | sudo tee -a /etc/fstab

# Test configuration
sudo mount -a
df -h | grep encrypted

LUKS Key Management

# View current key slots
sudo cryptsetup luksDump /dev/sdb1

# Add additional passphrase/key (up to 8 key slots)
sudo cryptsetup luksAddKey /dev/sdb1

# Remove a key slot (requires another valid key)
sudo cryptsetup luksRemoveKey /dev/sdb1

# Change passphrase
sudo cryptsetup luksChangeKey /dev/sdb1

# Kill a specific key slot (if you know which slot)
sudo cryptsetup luksKillSlot /dev/sdb1 1

# Backup LUKS header (critical for recovery)
sudo cryptsetup luksHeaderBackup /dev/sdb1 --header-backup-file /secure/backup/sdb1-luks-header.img

# Restore LUKS header (if corrupted)
# sudo cryptsetup luksHeaderRestore /dev/sdb1 --header-backup-file /secure/backup/sdb1-luks-header.img

Performance Tuning for LUKS

# Check current cipher and key size
sudo cryptsetup luksDump /dev/sdb1 | grep -E "Cipher|Key"

# Benchmark different ciphers
cryptsetup benchmark

# Create LUKS volume with specific cipher and key size
sudo cryptsetup luksFormat /dev/sdb1 \
    --cipher aes-xts-plain64 \
    --key-size 512 \
    --hash sha256 \
    --iter-time 2000

# Check if AES-NI hardware acceleration is available
grep -m1 -o aes /proc/cpuinfo

# Monitor encryption performance
sudo cryptsetup luksDump /dev/sdb1
sudo dmsetup table encrypted_volume

LUKS Encryption for LVM

Encrypting LVM (Logical Volume Manager) volumes provides flexibility for dynamic volume management:

# Create encrypted partition first
sudo cryptsetup luksFormat /dev/sdb1
sudo cryptsetup luksOpen /dev/sdb1 encrypted_pv

# Create LVM physical volume on encrypted device
sudo pvcreate /dev/mapper/encrypted_pv

# Create volume group
sudo vgcreate encrypted_vg /dev/mapper/encrypted_pv

# Create logical volumes
sudo lvcreate -L 50G -n data encrypted_vg
sudo lvcreate -L 30G -n backups encrypted_vg

# Create file systems
sudo mkfs.ext4 /dev/encrypted_vg/data
sudo mkfs.ext4 /dev/encrypted_vg/backups

# Mount volumes
sudo mkdir -p /mnt/data /mnt/backups
sudo mount /dev/encrypted_vg/data /mnt/data
sudo mount /dev/encrypted_vg/backups /mnt/backups

# Add to /etc/crypttab and /etc/fstab for automatic mounting
echo "encrypted_pv /dev/sdb1 /root/luks-keys/lvm.key luks" | sudo tee -a /etc/crypttab
echo "/dev/encrypted_vg/data /mnt/data ext4 defaults 0 2" | sudo tee -a /etc/fstab
echo "/dev/encrypted_vg/backups /mnt/backups ext4 defaults 0 2" | sudo tee -a /etc/fstab

File System Level Encryption

eCryptfs - Stacked File System Encryption

eCryptfs encrypts individual files and directories without requiring dedicated partitions:

# Install eCryptfs
sudo apt-get install -y ecryptfs-utils # Debian/Ubuntu
sudo yum install -y ecryptfs-utils # RHEL/CentOS

# Create directories
sudo mkdir -p /encrypted-data
sudo mkdir -p /mnt/decrypted

# Mount encrypted directory
sudo mount -t ecryptfs /encrypted-data /mnt/decrypted

# You will be prompted for:
# - Passphrase
# - Cipher (aes recommended)
# - Key bytes (16 = 128-bit, 32 = 256-bit)
# - Enable plaintext passthrough (no)
# - Enable filename encryption (yes for maximum security)

# Save the mount options shown for future use

# Use the decrypted mount point normally
echo "Sensitive file content" | sudo tee /mnt/decrypted/secret.txt

# Files are encrypted in /encrypted-data
sudo ls -la /encrypted-data  # Shows encrypted filenames
cat /encrypted-data/*  # Shows encrypted content

# Files are readable in /mnt/decrypted
cat /mnt/decrypted/secret.txt  # Shows plaintext

# Unmount when done
sudo umount /mnt/decrypted

# Automate mounting via /etc/fstab
echo "/encrypted-data /mnt/decrypted ecryptfs defaults 0 0" | sudo tee -a /etc/fstab
# Note: Still requires interactive passphrase unless using key file

FSCRYPT - Native File System Encryption

FSCRYPT provides native encryption for ext4, F2FS, and UBIFS file systems:

# Install fscrypt
sudo apt-get install -y fscrypt libpam-fscrypt # Debian/Ubuntu

# Setup fscrypt on file system
sudo fscrypt setup

# Setup fscrypt on specific mount point
sudo fscrypt setup /home

# Create encrypted directory
sudo mkdir /home/encrypted_project
sudo fscrypt encrypt /home/encrypted_project

# Choose encryption policy:
# 1. Your login passphrase
# 2. A custom passphrase
# 3. A raw key file

# Use the encrypted directory
echo "secret data" | sudo tee /home/encrypted_project/data.txt

# View encryption status
sudo fscrypt status /home/encrypted_project

# Lock directory (makes it inaccessible)
sudo fscrypt lock /home/encrypted_project

# Unlock directory
sudo fscrypt unlock /home/encrypted_project

# Change passphrase
sudo fscrypt metadata change-passphrase --protector=/home

EncFS - Userspace Encrypted File System

EncFS provides encryption in userspace, useful for cloud storage scenarios:

# Install EncFS
sudo apt-get install -y encfs # Debian/Ubuntu
sudo yum install -y encfs # RHEL/CentOS

# Create directories
mkdir -p ~/encrypted-source
mkdir -p ~/encrypted-mount

# Create encrypted file system
encfs ~/encrypted-source ~/encrypted-mount

# Choose configuration:
# - x (expert mode) for custom settings
# - p (paranoid mode) for maximum security
# - Standard configuration for defaults

# Set encryption password

# Use mounted directory
echo "secret" > ~/encrypted-mount/file.txt

# Data is encrypted in source directory
cat ~/encrypted-source/*  # Encrypted content

# Unmount
fusermount -u ~/encrypted-mount

# Remount with saved configuration
encfs ~/encrypted-source ~/encrypted-mount

# Automount on login (add to ~/.bashrc)
echo "encfs ~/encrypted-source ~/encrypted-mount" >> ~/.bashrc

Database Encryption at Rest

MySQL/MariaDB Encryption

Table-Level Encryption

# Enable encryption plugin
sudo tee -a /etc/mysql/mariadb.conf.d/50-server.cnf << 'EOF'

[mysqld]
# Encryption plugin
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfile.enc
file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
file_key_management_encryption_algorithm = AES_CTR

# Enable encryption features
innodb_encrypt_tables = ON
innodb_encrypt_log = ON
innodb_encryption_threads = 4
encrypt_binlog = ON
encrypt_tmp_files = ON

EOF

# Create encryption key directory
sudo mkdir -p /etc/mysql/encryption
sudo chmod 750 /etc/mysql/encryption
sudo chown mysql:mysql /etc/mysql/encryption

# Generate encryption keys
# Master key
sudo openssl rand -hex 32 > /etc/mysql/encryption/keyfile.key
sudo chmod 600 /etc/mysql/encryption/keyfile.key
sudo chown mysql:mysql /etc/mysql/encryption/keyfile.key

# Data encryption keys file
cat | sudo tee /etc/mysql/encryption/keyfile.enc << 'EOF'
1;0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
2;FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210
EOF

sudo chmod 600 /etc/mysql/encryption/keyfile.enc
sudo chown mysql:mysql /etc/mysql/encryption/keyfile.enc

# Restart MySQL
sudo systemctl restart mysql

# Verify encryption status
mysql -u root -p -e "SHOW VARIABLES LIKE '%encrypt%';"

# Create encrypted table
mysql -u root -p << 'EOF'
CREATE DATABASE encrypted_db;
USE encrypted_db;

CREATE TABLE sensitive_data (
    id INT PRIMARY KEY AUTO_INCREMENT,
    customer_name VARCHAR(255),
    credit_card VARBINARY(256),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENCRYPTED=YES ENCRYPTION_KEY_ID=1;

-- Verify table encryption
SELECT
    TABLE_SCHEMA,
    TABLE_NAME,
    CREATE_OPTIONS
FROM
    INFORMATION_SCHEMA.TABLES
WHERE
    TABLE_SCHEMA = 'encrypted_db';

EOF

# Encrypt existing unencrypted tables
mysql -u root -p << 'EOF'
USE your_database;
ALTER TABLE existing_table ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
EOF

Tablespace Encryption

# Enable general tablespace encryption
mysql -u root -p << 'EOF'
-- Set default encryption for new tables
SET GLOBAL default_table_encryption=ON;

-- Encrypt system tablespace
ALTER INSTANCE ROTATE INNODB MASTER KEY;

-- Create encrypted tablespace
CREATE TABLESPACE encrypted_space
    ADD DATAFILE 'encrypted_space.ibd'
    ENCRYPTION='Y';

-- Create table in encrypted tablespace
CREATE TABLE secure_data (
    id INT PRIMARY KEY,
    data TEXT
) TABLESPACE=encrypted_space;

-- Check encryption status
SELECT
    SPACE,
    NAME,
    SPACE_TYPE,
    ENCRYPTION
FROM
    INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE
    ENCRYPTION='Y';

EOF

Key Rotation

# Create key rotation script
cat > /root/scripts/mysql_key_rotation.sh << 'EOF'
#!/bin/bash
# MySQL Encryption Key Rotation

LOG_FILE="/var/log/mysql/key_rotation.log"

echo "$(date): Starting MySQL encryption key rotation" | tee -a "$LOG_FILE"

# Backup current keys
cp /etc/mysql/encryption/keyfile.enc /etc/mysql/encryption/keyfile.enc.backup.$(date +%Y%m%d)

# Generate new key
NEW_KEY=$(openssl rand -hex 32)
NEW_KEY_ID=$(($(tail -1 /etc/mysql/encryption/keyfile.enc | cut -d';' -f1) + 1))

# Add new key to keyfile
echo "${NEW_KEY_ID};${NEW_KEY}" | sudo tee -a /etc/mysql/encryption/keyfile.enc

# Rotate master key
mysql -u root -p -e "ALTER INSTANCE ROTATE INNODB MASTER KEY;" 2>&1 | tee -a "$LOG_FILE"

echo "$(date): Key rotation completed. New key ID: ${NEW_KEY_ID}" | tee -a "$LOG_FILE"
echo "Remember to re-encrypt tables with new key ID if needed." | tee -a "$LOG_FILE"

EOF

chmod +x /root/scripts/mysql_key_rotation.sh

# Schedule annual key rotation
echo "0 2 1 1 * /root/scripts/mysql_key_rotation.sh" | sudo crontab -

PostgreSQL Encryption

PostgreSQL doesn't have native table-level encryption, but offers several encryption options:

pgcrypto Extension

# Enable pgcrypto extension
sudo -u postgres psql -c "CREATE EXTENSION IF NOT EXISTS pgcrypto;"

# Create table with encrypted columns
sudo -u postgres psql << 'EOF'
CREATE DATABASE encrypted_db;
\c encrypted_db

-- Create table with encryption
CREATE TABLE sensitive_users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50),
    email_encrypted BYTEA,
    ssn_encrypted BYTEA,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Insert encrypted data
INSERT INTO sensitive_users (username, email_encrypted, ssn_encrypted)
VALUES (
    'john_doe',
    pgp_sym_encrypt('[email protected]', 'encryption_passphrase'),
    pgp_sym_encrypt('123-45-6789', 'encryption_passphrase')
);

-- Query encrypted data
SELECT
    id,
    username,
    pgp_sym_decrypt(email_encrypted, 'encryption_passphrase') AS email,
    pgp_sym_decrypt(ssn_encrypted, 'encryption_passphrase') AS ssn
FROM
    sensitive_users;

-- Create functions for encryption/decryption
CREATE OR REPLACE FUNCTION encrypt_data(plaintext TEXT, key TEXT)
RETURNS BYTEA AS $$
BEGIN
    RETURN pgp_sym_encrypt(plaintext, key);
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION decrypt_data(ciphertext BYTEA, key TEXT)
RETURNS TEXT AS $$
BEGIN
    RETURN pgp_sym_decrypt(ciphertext, key);
END;
$$ LANGUAGE plpgsql;

EOF

File System Level Encryption for PostgreSQL

Since PostgreSQL lacks native transparent data encryption, use file system or disk encryption:

# Stop PostgreSQL
sudo systemctl stop postgresql

# Backup current data directory
sudo rsync -av /var/lib/postgresql/ /backup/postgresql/

# Create encrypted volume for PostgreSQL data
sudo cryptsetup luksFormat /dev/sdc1
sudo cryptsetup luksOpen /dev/sdc1 postgres_encrypted
sudo mkfs.ext4 /dev/mapper/postgres_encrypted

# Mount encrypted volume
sudo mount /dev/mapper/postgres_encrypted /var/lib/postgresql

# Restore data
sudo rsync -av /backup/postgresql/ /var/lib/postgresql/
sudo chown -R postgres:postgres /var/lib/postgresql

# Configure automatic mounting
echo "postgres_encrypted /dev/sdc1 /root/luks-keys/postgres.key luks" | sudo tee -a /etc/crypttab
echo "/dev/mapper/postgres_encrypted /var/lib/postgresql ext4 defaults 0 2" | sudo tee -a /etc/fstab

# Start PostgreSQL
sudo systemctl start postgresql

MongoDB Encryption

MongoDB Enterprise supports encryption at rest natively:

# Configure MongoDB encryption (Enterprise only)
sudo tee -a /etc/mongod.conf << 'EOF'

security:
  enableEncryption: true
  encryptionKeyFile: /etc/mongodb/encryption/mongodb.key

EOF

# Generate encryption key
sudo mkdir -p /etc/mongodb/encryption
sudo openssl rand -base64 32 > /etc/mongodb/encryption/mongodb.key
sudo chmod 600 /etc/mongodb/encryption/mongodb.key
sudo chown mongodb:mongodb /etc/mongodb/encryption/mongodb.key

# Restart MongoDB
sudo systemctl restart mongod

# For MongoDB Community Edition, use LUKS disk encryption
# Follow same process as PostgreSQL example above

Application-Level Encryption

Application-level encryption provides fine-grained control over what data is encrypted and how keys are managed.

Python Example

#!/usr/bin/env python3
# Application-level encryption example

from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2
from cryptography.hazmat.backends import default_backend
import base64
import os

class DataEncryption:
    def __init__(self, passphrase=None, key_file=None):
        if key_file and os.path.exists(key_file):
            with open(key_file, 'rb') as f:
                self.key = f.read()
        elif passphrase:
            # Derive key from passphrase
            salt = b'static_salt_replace_with_random'  # In production, use random salt stored separately
            kdf = PBKDF2(
                algorithm=hashes.SHA256(),
                length=32,
                salt=salt,
                iterations=100000,
                backend=default_backend()
            )
            key = base64.urlsafe_b64encode(kdf.derive(passphrase.encode()))
            self.key = key
        else:
            # Generate new key
            self.key = Fernet.generate_key()

        self.cipher = Fernet(self.key)

    def save_key(self, key_file):
        """Save encryption key to file"""
        with open(key_file, 'wb') as f:
            f.write(self.key)
        os.chmod(key_file, 0o400)

    def encrypt(self, plaintext):
        """Encrypt plaintext string"""
        if isinstance(plaintext, str):
            plaintext = plaintext.encode()
        return self.cipher.encrypt(plaintext)

    def decrypt(self, ciphertext):
        """Decrypt ciphertext to string"""
        plaintext = self.cipher.decrypt(ciphertext)
        return plaintext.decode()

# Usage example
if __name__ == "__main__":
    # Initialize with passphrase
    encryptor = DataEncryption(passphrase="strong_application_password")

    # Encrypt sensitive data
    sensitive_data = "Credit Card: 4111-1111-1111-1111"
    encrypted = encryptor.encrypt(sensitive_data)
    print(f"Encrypted: {encrypted}")

    # Decrypt data
    decrypted = encryptor.decrypt(encrypted)
    print(f"Decrypted: {decrypted}")

    # Save key for future use
    encryptor.save_key("/etc/app/encryption.key")

PHP Example

<?php
// Application-level encryption in PHP

class DataEncryption {
    private $key;
    private $cipher = "aes-256-gcm";

    public function __construct($keyFile = null) {
        if ($keyFile && file_exists($keyFile)) {
            $this->key = file_get_contents($keyFile);
        } else {
            // Generate new key
            $this->key = random_bytes(32);
        }
    }

    public function saveKey($keyFile) {
        file_put_contents($keyFile, $this->key);
        chmod($keyFile, 0400);
    }

    public function encrypt($plaintext) {
        $ivlen = openssl_cipher_iv_length($this->cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $tag = "";

        $ciphertext = openssl_encrypt(
            $plaintext,
            $this->cipher,
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag
        );

        // Combine IV, tag, and ciphertext for storage
        return base64_encode($iv . $tag . $ciphertext);
    }

    public function decrypt($encrypted) {
        $data = base64_decode($encrypted);

        $ivlen = openssl_cipher_iv_length($this->cipher);
        $iv = substr($data, 0, $ivlen);
        $tag = substr($data, $ivlen, 16);
        $ciphertext = substr($data, $ivlen + 16);

        $plaintext = openssl_decrypt(
            $ciphertext,
            $this->cipher,
            $this->key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag
        );

        return $plaintext;
    }
}

// Usage
$encryptor = new DataEncryption();
$encryptor->saveKey("/etc/app/encryption.key");

$sensitive = "Customer SSN: 123-45-6789";
$encrypted = $encryptor->encrypt($sensitive);
echo "Encrypted: " . $encrypted . "\n";

$decrypted = $encryptor->decrypt($encrypted);
echo "Decrypted: " . $decrypted . "\n";
?>

Bash Script Example

#!/bin/bash
# Simple file encryption/decryption script

CIPHER="aes-256-cbc"
KEY_FILE="/etc/encryption/master.key"
SALT="$(openssl rand -hex 16)"

# Generate key file if it doesn't exist
if [ ! -f "$KEY_FILE" ]; then
    mkdir -p "$(dirname $KEY_FILE)"
    openssl rand -base64 32 > "$KEY_FILE"
    chmod 400 "$KEY_FILE"
fi

encrypt_file() {
    local input_file="$1"
    local output_file="${input_file}.enc"

    if [ ! -f "$input_file" ]; then
        echo "Error: Input file not found"
        return 1
    fi

    openssl enc -$CIPHER -salt -in "$input_file" -out "$output_file" -pass file:"$KEY_FILE" -pbkdf2

    if [ $? -eq 0 ]; then
        echo "File encrypted: $output_file"
        # Optionally securely delete original
        # shred -vfz -n 5 "$input_file"
    else
        echo "Encryption failed"
        return 1
    fi
}

decrypt_file() {
    local input_file="$1"
    local output_file="${input_file%.enc}"

    if [ ! -f "$input_file" ]; then
        echo "Error: Input file not found"
        return 1
    fi

    openssl enc -d -$CIPHER -in "$input_file" -out "$output_file" -pass file:"$KEY_FILE" -pbkdf2

    if [ $? -eq 0 ]; then
        echo "File decrypted: $output_file"
    else
        echo "Decryption failed"
        return 1
    fi
}

# Usage
case "$1" in
    encrypt)
        encrypt_file "$2"
        ;;
    decrypt)
        decrypt_file "$2"
        ;;
    *)
        echo "Usage: $0 {encrypt|decrypt} <file>"
        exit 1
        ;;
esac

Key Management Best Practices

Hardware Security Module (HSM) Integration

For production environments handling sensitive data, HSMs provide the highest level of key security:

# Example: Using SoftHSM for testing/development
# (Use actual HSM hardware in production)

# Install SoftHSM
sudo apt-get install -y softhsm2

# Initialize token
softhsm2-util --init-token --slot 0 --label "EncryptionKeys"

# Import key to HSM
softhsm2-util --import /path/to/key.pem --slot 0 --label "DataKey" --id 0001

# List tokens
softhsm2-util --show-slots

# Use PKCS#11 interface to access keys
# Most encryption tools support PKCS#11

Cloud KMS Integration

AWS KMS Example

# Install AWS CLI
sudo apt-get install -y awscli

# Configure AWS credentials
aws configure

# Create KMS key
aws kms create-key --description "Data Encryption Key"

# Get key ID from output
KEY_ID="arn:aws:kms:region:account:key/key-id"

# Encrypt data
echo "sensitive data" | aws kms encrypt \
    --key-id "$KEY_ID" \
    --plaintext fileb:///dev/stdin \
    --output text \
    --query CiphertextBlob | base64 -d > encrypted_data.bin

# Decrypt data
aws kms decrypt \
    --ciphertext-blob fileb://encrypted_data.bin \
    --output text \
    --query Plaintext | base64 -d

Key Rotation Strategy

# Create comprehensive key rotation script
cat > /root/scripts/encryption_key_rotation.sh << 'EOF'
#!/bin/bash
# Comprehensive Encryption Key Rotation

LOG_FILE="/var/log/security/key_rotation_$(date +%Y%m%d).log"
mkdir -p "$(dirname $LOG_FILE)"

exec > >(tee -a "$LOG_FILE")
exec 2>&1

echo "========================================"
echo "ENCRYPTION KEY ROTATION"
echo "Started: $(date)"
echo "========================================"
echo ""

# 1. LUKS Key Rotation
echo "=== LUKS Key Rotation ==="
LUKS_DEVICES=$(lsblk -o NAME,FSTYPE | grep crypto_LUKS | awk '{print "/dev/"$1}')

for device in $LUKS_DEVICES; do
    echo "Processing $device..."

    # Generate new key
    NEW_KEY_FILE="/root/luks-keys/$(basename $device).key.new"
    dd if=/dev/urandom of="$NEW_KEY_FILE" bs=4096 count=1 2>/dev/null
    chmod 400 "$NEW_KEY_FILE"

    # Add new key
    cryptsetup luksAddKey "$device" "$NEW_KEY_FILE"

    # Remove old key (requires current key)
    OLD_KEY_FILE="/root/luks-keys/$(basename $device).key"
    if [ -f "$OLD_KEY_FILE" ]; then
        cryptsetup luksRemoveKey "$device" "$OLD_KEY_FILE"
        shred -vfz -n 5 "$OLD_KEY_FILE"
    fi

    # Rename new key to current
    mv "$NEW_KEY_FILE" "$OLD_KEY_FILE"

    echo "$device: Key rotated successfully"
done
echo ""

# 2. MySQL Encryption Key Rotation
echo "=== MySQL Key Rotation ==="
if systemctl is-active --quiet mysql; then
    mysql -u root -p -e "ALTER INSTANCE ROTATE INNODB MASTER KEY;" 2>/dev/null
    echo "MySQL master key rotated"
fi
echo ""

# 3. Application Key Rotation
echo "=== Application Key Rotation ==="
APP_KEY_DIR="/etc/app/encryption"
if [ -d "$APP_KEY_DIR" ]; then
    for key_file in "$APP_KEY_DIR"/*.key; do
        if [ -f "$key_file" ]; then
            # Backup old key
            cp "$key_file" "$key_file.old.$(date +%Y%m%d)"

            # Generate new key
            openssl rand -base64 32 > "$key_file"
            chmod 400 "$key_file"

            echo "Rotated: $key_file"
            echo "NOTE: Application must re-encrypt data with new key"
        fi
    done
fi
echo ""

# 4. Document rotation
cat > "/root/key-rotation-records/rotation_$(date +%Y%m%d).txt" << RECORD
Key Rotation Record
Date: $(date)
Rotated by: $(whoami)

LUKS devices rotated: $(echo "$LUKS_DEVICES" | wc -l)
MySQL keys rotated: Yes
Application keys rotated: Yes

Next rotation due: $(date -d "+1 year" +%Y-%m-%d)

RECORD

echo "========================================"
echo "KEY ROTATION COMPLETED: $(date)"
echo "========================================"
echo ""
echo "REQUIRED ACTIONS:"
echo "1. Verify all encrypted volumes still accessible"
echo "2. Test database connectivity and encryption"
echo "3. Re-encrypt application data with new keys"
echo "4. Securely destroy old key backups after verification (30 days)"
echo "5. Update disaster recovery documentation"

EOF

chmod +x /root/scripts/encryption_key_rotation.sh

# Schedule annual key rotation
echo "0 3 1 1 * /root/scripts/encryption_key_rotation.sh" | sudo crontab -

Encryption Monitoring and Auditing

Encryption Status Monitoring

# Create comprehensive encryption monitoring script
cat > /root/scripts/encryption_monitor.sh << 'EOF'
#!/bin/bash
# Encryption at Rest Monitoring

REPORT_FILE="/var/log/security/encryption_status_$(date +%Y%m%d).txt"
ALERT_EMAIL="[email protected]"

exec > >(tee -a "$REPORT_FILE")

echo "========================================"
echo "ENCRYPTION STATUS REPORT"
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo "========================================"
echo ""

# Check LUKS encrypted volumes
echo "=== LUKS Encrypted Volumes ==="
LUKS_COUNT=0
lsblk -o NAME,TYPE,FSTYPE,MOUNTPOINT,SIZE | while read line; do
    if echo "$line" | grep -q "crypto_LUKS"; then
        echo "$line"
        ((LUKS_COUNT++))
    fi
done
echo "Total LUKS volumes: $LUKS_COUNT"
echo ""

# Check currently open encrypted volumes
echo "=== Active Encrypted Volumes ==="
ls -l /dev/mapper/ | grep -v "control"
echo ""

# Check MySQL encryption
echo "=== MySQL Encryption Status ==="
if systemctl is-active --quiet mysql mariadb; then
    mysql -u root -p -e "
        SELECT @@innodb_encrypt_tables,
               @@innodb_encrypt_log,
               @@encrypt_binlog,
               @@encrypt_tmp_files;
    " 2>/dev/null

    echo ""
    echo "Encrypted Tables:"
    mysql -u root -p -e "
        SELECT COUNT(*) as encrypted_tables
        FROM INFORMATION_SCHEMA.TABLES
        WHERE CREATE_OPTIONS LIKE '%ENCRYPTED=YES%';
    " 2>/dev/null
fi
echo ""

# Check PostgreSQL pgcrypto
echo "=== PostgreSQL Encryption ==="
if systemctl is-active --quiet postgresql; then
    sudo -u postgres psql -c "\dx pgcrypto" 2>/dev/null
fi
echo ""

# Check file system encryption
echo "=== File System Encryption ==="
mount | grep -E "ecryptfs|encfs|fscrypt"
echo ""

# Check for unencrypted sensitive directories
echo "=== Unencrypted Sensitive Data Warning ==="
SENSITIVE_DIRS="/var/backups /opt/app/data /var/www/uploads"
for dir in $SENSITIVE_DIRS; do
    if [ -d "$dir" ]; then
        # Check if directory is on encrypted volume
        MOUNT_POINT=$(df "$dir" | tail -1 | awk '{print $1}')
        if ! lsblk -o NAME,FSTYPE "$MOUNT_POINT" 2>/dev/null | grep -q "crypto_LUKS"; then
            echo "WARNING: $dir is NOT on encrypted volume!"
            echo "  Mount point: $MOUNT_POINT"
        else
            echo "OK: $dir is encrypted"
        fi
    fi
done
echo ""

# Check encryption key file permissions
echo "=== Encryption Key Security ==="
find /root/luks-keys /etc/mysql/encryption /etc/app/encryption -type f 2>/dev/null | while read key_file; do
    PERMS=$(stat -c "%a" "$key_file")
    OWNER=$(stat -c "%U:%G" "$key_file")

    if [ "$PERMS" != "400" ] && [ "$PERMS" != "600" ]; then
        echo "WARNING: Weak permissions on $key_file: $PERMS (should be 400 or 600)"
    fi

    if [ "$OWNER" != "root:root" ] && [ "$OWNER" != "mysql:mysql" ]; then
        echo "WARNING: Incorrect ownership on $key_file: $OWNER"
    fi
done
echo ""

echo "========================================"
echo "REPORT COMPLETED: $(date)"
echo "========================================"

# Alert if warnings found
if grep -q "WARNING" "$REPORT_FILE"; then
    echo "Encryption warnings detected!" | mail -s "Encryption Status Alert" -a "$REPORT_FILE" "$ALERT_EMAIL"
fi

EOF

chmod +x /root/scripts/encryption_monitor.sh

# Schedule daily monitoring
echo "0 8 * * * /root/scripts/encryption_monitor.sh" | sudo crontab -

Compliance Audit Script

# Create encryption compliance audit script
cat > /root/scripts/encryption_compliance_audit.sh << 'EOF'
#!/bin/bash
# Encryption at Rest Compliance Audit

AUDIT_FILE="/var/log/security/encryption_audit_$(date +%Y%m%d).txt"

exec > >(tee -a "$AUDIT_FILE")

echo "========================================"
echo "ENCRYPTION COMPLIANCE AUDIT"
echo "Date: $(date)"
echo "Auditor: $(whoami)"
echo "========================================"
echo ""

# Compliance checklist
echo "=== COMPLIANCE CHECKLIST ==="
echo ""

# 1. Encryption Algorithm Strength
echo "[ ] Requirement: AES-256 or stronger encryption"
cryptsetup luksDump /dev/sdb1 2>/dev/null | grep -E "Cipher|Key"
echo ""

# 2. Key Storage
echo "[ ] Requirement: Encryption keys stored separately from data"
echo "Key locations:"
find / -name "*.key" -type f 2>/dev/null | grep -E "luks|encryption|mysql|app"
echo ""

# 3. Key Permissions
echo "[ ] Requirement: Key files have restrictive permissions (400/600)"
find /root/luks-keys /etc/mysql/encryption /etc/app/encryption -type f 2>/dev/null -exec ls -la {} \;
echo ""

# 4. Key Rotation
echo "[ ] Requirement: Keys rotated at least annually"
echo "Last key rotation:"
ls -lt /root/key-rotation-records/ 2>/dev/null | head -5
echo ""

# 5. Data at Rest Coverage
echo "[ ] Requirement: All sensitive data encrypted at rest"
echo "Sensitive data locations and encryption status:"
for dir in /var/backups /opt/app/data /var/www/uploads /home; do
    if [ -d "$dir" ]; then
        MOUNT=$(df "$dir" | tail -1 | awk '{print $1}')
        ENCRYPTED=$(lsblk -o NAME,FSTYPE "$MOUNT" 2>/dev/null | grep -c "crypto_LUKS")
        if [ "$ENCRYPTED" -gt 0 ]; then
            echo "✓ $dir: ENCRYPTED"
        else
            echo "✗ $dir: NOT ENCRYPTED"
        fi
    fi
done
echo ""

# 6. Database Encryption
echo "[ ] Requirement: Database files encrypted"
if systemctl is-active --quiet mysql mariadb; then
    mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb_encrypt%';" 2>/dev/null
fi
echo ""

# 7. Backup Encryption
echo "[ ] Requirement: Backups encrypted"
echo "Checking backup files..."
find /var/backups -name "*.tar.gz" -o -name "*.sql" 2>/dev/null | head -5
echo "Verify these are encrypted or on encrypted volumes"
echo ""

# 8. Key Backup
echo "[ ] Requirement: Encryption keys backed up securely"
echo "LUKS header backups:"
find /secure/backups -name "*luks-header*" 2>/dev/null
echo ""

# 9. Documentation
echo "[ ] Requirement: Encryption procedures documented"
echo "Documentation files:"
find /root/docs /opt/docs -name "*encryption*" -o -name "*key-management*" 2>/dev/null
echo ""

# 10. Access Logging
echo "[ ] Requirement: Access to encrypted data logged"
ausearch -k encrypted_data_access -ts today 2>/dev/null | wc -l
echo ""

echo "========================================"
echo "AUDIT COMPLETED"
echo "Report saved to: $AUDIT_FILE"
echo "========================================"
echo ""
echo "REMEDIATION REQUIRED:"
echo "1. Address any checklist items marked with ✗"
echo "2. Ensure all sensitive data is on encrypted volumes"
echo "3. Verify key rotation schedule is being followed"
echo "4. Update documentation to reflect current state"
echo "5. Schedule next audit for: $(date -d '+3 months' +%Y-%m-%d)"

EOF

chmod +x /root/scripts/encryption_compliance_audit.sh

Disaster Recovery and Key Management

LUKS Header Backup and Recovery

# Backup LUKS headers for all encrypted devices
cat > /root/scripts/backup_luks_headers.sh << 'EOF'
#!/bin/bash
# Backup LUKS Headers

BACKUP_DIR="/secure/backups/luks-headers"
mkdir -p "$BACKUP_DIR"

echo "Backing up LUKS headers..."

# Find all LUKS devices
lsblk -o NAME,FSTYPE | grep crypto_LUKS | awk '{print "/dev/"$1}' | while read device; do
    BACKUP_FILE="$BACKUP_DIR/$(basename $device)-header-$(date +%Y%m%d).img"

    echo "Backing up $device to $BACKUP_FILE"
    cryptsetup luksHeaderBackup "$device" --header-backup-file "$BACKUP_FILE"

    # Encrypt the backup
    gpg --symmetric --cipher-algo AES256 "$BACKUP_FILE"

    # Remove unencrypted backup
    shred -vfz "$BACKUP_FILE"

    echo "Backup completed: $BACKUP_FILE.gpg"
done

echo "All LUKS headers backed up successfully"
echo "Store these backups in a secure, off-site location"

EOF

chmod +x /root/scripts/backup_luks_headers.sh

# Recovery procedure (document this)
cat > /root/docs/luks_recovery.md << 'EOF'
# LUKS Header Recovery Procedure

## When to Use
- LUKS header is corrupted
- Cannot open encrypted volume
- "Device or resource busy" errors

## Recovery Steps

1. Identify corrupted device:
   ```bash
   cryptsetup luksDump /dev/sdX
   # If this fails, header is likely corrupted
  1. Decrypt backup:

    gpg --decrypt /secure/backups/luks-headers/sdX-header-YYYYMMDD.img.gpg > /tmp/header.img
    
  2. Restore header:

    cryptsetup luksHeaderRestore /dev/sdX --header-backup-file /tmp/header.img
    
  3. Verify restoration:

    cryptsetup luksDump /dev/sdX
    cryptsetup luksOpen /dev/sdX test_volume
    
  4. Secure cleanup:

    shred -vfz /tmp/header.img
    

Important Notes

  • NEVER restore a header to the wrong device
  • Always verify device UUID before restoration
  • Test recovery procedure regularly
  • Keep multiple header backups from different dates

EOF


### Encryption Key Backup Procedure

```bash
# Create secure key backup script
cat > /root/scripts/backup_encryption_keys.sh << 'EOF'
#!/bin/bash
# Secure Encryption Key Backup

BACKUP_DIR="/secure/backups/keys"
BACKUP_FILE="$BACKUP_DIR/encryption-keys-$(date +%Y%m%d).tar.gz.gpg"
TEMP_DIR="/tmp/key-backup-$$"

mkdir -p "$BACKUP_DIR"
mkdir -p "$TEMP_DIR"

echo "Creating encryption key backup..."

# Collect all encryption keys
cp -r /root/luks-keys "$TEMP_DIR/" 2>/dev/null
cp -r /etc/mysql/encryption "$TEMP_DIR/" 2>/dev/null
cp -r /etc/app/encryption "$TEMP_DIR/" 2>/dev/null

# Create tarball
tar -czf "$TEMP_DIR/keys.tar.gz" -C "$TEMP_DIR" .

# Encrypt backup with GPG
gpg --symmetric --cipher-algo AES256 --output "$BACKUP_FILE" "$TEMP_DIR/keys.tar.gz"

# Secure cleanup
shred -vfz -n 5 "$TEMP_DIR"/keys.tar.gz
rm -rf "$TEMP_DIR"

echo "Key backup completed: $BACKUP_FILE"
echo "Store this backup in a secure, off-site location"
echo "CRITICAL: Document the GPG passphrase in your password manager"

# Calculate checksum
sha256sum "$BACKUP_FILE" > "$BACKUP_FILE.sha256"

EOF

chmod +x /root/scripts/backup_encryption_keys.sh

# Schedule monthly key backups
echo "0 4 1 * * /root/scripts/backup_encryption_keys.sh" | sudo crontab -

Performance Considerations

Encryption Performance Testing

# Create encryption performance benchmark script
cat > /root/scripts/encryption_benchmark.sh << 'EOF'
#!/bin/bash
# Encryption Performance Benchmark

REPORT_FILE="/tmp/encryption_benchmark_$(date +%Y%m%d).txt"

exec > >(tee "$REPORT_FILE")

echo "========================================"
echo "ENCRYPTION PERFORMANCE BENCHMARK"
echo "Date: $(date)"
echo "========================================"
echo ""

# 1. CPU Cryptography Capabilities
echo "=== CPU Capabilities ==="
echo "AES-NI Support:"
grep -m1 -o aes /proc/cpuinfo && echo "Yes" || echo "No"
echo ""
echo "CPU Model:"
grep "model name" /proc/cpuinfo | head -1
echo ""

# 2. Cryptsetup Benchmark
echo "=== Cryptsetup Cipher Benchmark ==="
cryptsetup benchmark
echo ""

# 3. OpenSSL Speed Test
echo "=== OpenSSL Benchmark ==="
openssl speed -elapsed aes-128-cbc aes-256-cbc
echo ""

# 4. Disk I/O Performance (unencrypted vs encrypted)
echo "=== Disk I/O Performance Comparison ==="

# Test unencrypted partition
echo "Unencrypted write test:"
dd if=/dev/zero of=/tmp/test.img bs=1M count=1024 conv=fdatasync 2>&1 | grep -E "copied|s,"

# Test encrypted partition (if mounted)
if mount | grep -q "/mnt/encrypted"; then
    echo "Encrypted write test:"
    dd if=/dev/zero of=/mnt/encrypted/test.img bs=1M count=1024 conv=fdatasync 2>&1 | grep -E "copied|s,"
    rm /mnt/encrypted/test.img
fi

rm /tmp/test.img
echo ""

# 5. Database Performance
echo "=== Database Performance Impact ==="
if systemctl is-active --quiet mysql; then
    echo "Testing MySQL query performance with encryption..."
    mysql -u root -p -e "
        USE test;
        DROP TABLE IF EXISTS perf_test;
        CREATE TABLE perf_test (
            id INT AUTO_INCREMENT PRIMARY KEY,
            data VARCHAR(255)
        );

        -- Insert test data
        INSERT INTO perf_test (data) VALUES ('test');
        INSERT INTO perf_test (data) SELECT data FROM perf_test;
        INSERT INTO perf_test (data) SELECT data FROM perf_test;
        INSERT INTO perf_test (data) SELECT data FROM perf_test;

        -- Benchmark query
        SELECT BENCHMARK(1000000, (SELECT COUNT(*) FROM perf_test));

        DROP TABLE perf_test;
    " 2>/dev/null
fi
echo ""

echo "========================================"
echo "BENCHMARK COMPLETED"
echo "Report saved to: $REPORT_FILE"
echo "========================================"

EOF

chmod +x /root/scripts/encryption_benchmark.sh

Conclusion

Data encryption at rest is a critical security control that protects sensitive information from unauthorized access when storage media is compromised. This guide has provided comprehensive coverage of encryption implementation across multiple layers—from full disk encryption with LUKS to file system encryption, database encryption, and application-level encryption.

Key Takeaways

1. Defense in Depth: Implement encryption at multiple layers for maximum protection. Disk encryption protects against physical theft, while application-level encryption provides fine-grained control.

2. Key Management is Critical: The security of encrypted data depends entirely on proper key management. Use separate storage for keys, implement regular rotation, and maintain secure backups.

3. Performance Impact Varies: Full disk encryption with modern hardware (AES-NI) has minimal performance impact, while application-level encryption requires careful optimization.

4. Compliance Requirements: GDPR, PCI-DSS, HIPAA, and other regulations mandate encryption at rest for certain types of data. Proper implementation and documentation are essential for compliance.

5. Regular Testing: Test encryption, decryption, and recovery procedures regularly to ensure they work when needed.

Best Practices Summary

  • Use AES-256 encryption for all sensitive data
  • Store encryption keys separately from encrypted data
  • Implement automated key rotation (annually minimum)
  • Backup LUKS headers and encryption keys securely
  • Monitor encryption status continuously
  • Document all encryption procedures and key management processes
  • Test disaster recovery procedures regularly
  • Use hardware security modules (HSMs) for production environments
  • Enable audit logging for all access to encrypted data
  • Educate staff on encryption policies and procedures

Next Steps

  1. Immediate Actions:

    • Identify all sensitive data requiring encryption
    • Implement full disk encryption on new systems
    • Enable database encryption for existing databases
    • Document current encryption implementation
  2. Short-term (1-3 months):

    • Implement automated encryption monitoring
    • Establish key rotation procedures
    • Create backup and recovery procedures
    • Conduct encryption compliance audit
  3. Long-term:

    • Migrate to HSM or cloud KMS for key management
    • Implement application-level encryption for fine-grained control
    • Regular security audits and penetration testing
    • Continuous improvement of encryption practices

By implementing the techniques and procedures outlined in this guide, you'll establish a robust encryption at rest strategy that protects your organization's sensitive data against unauthorized access while maintaining compliance with regulatory requirements.