Security

Encryption at Rest: Key Management and Implementation Guide

A practical guide to encrypting data at rest — envelope encryption, KMS providers, field-level encryption, key rotation, and compliance considerations.

March 9, 20267 min readShipSafer Team

Encryption at Rest: Key Management and Implementation Guide

Encryption at rest protects data from unauthorized access when storage media is stolen, drives are decommissioned, or backup tapes are mishandled. It is a baseline requirement for virtually every compliance framework — GDPR, HIPAA, PCI DSS, SOC 2, and ISO 27001 all mandate it. But "enable encryption" is the easy part. Doing it in a way that actually provides meaningful protection — with proper key management, rotation, and separation of duties — is where organizations most often fall short.

What Encryption at Rest Protects (and What It Does Not)

Encryption at rest protects data when the storage medium is accessed outside of normal operation — stolen hard drives, unauthorized data center access, compromised backup media.

It does not protect against:

  • An attacker who gains access to your application (the application decrypts data to serve it)
  • A compromised database connection string (the database decrypts data for queries)
  • Cloud provider administrators with direct access to decryption keys

This is why key management — specifically, who controls the encryption keys — matters enormously. If your cloud provider holds your keys and is also running your database, their administrators can theoretically access your plaintext data. Customer-managed keys (CMK) address this by keeping key material under your control.

Envelope Encryption

Envelope encryption is the standard pattern for encrypting large amounts of data efficiently.

The pattern:

  1. Generate a Data Encryption Key (DEK) locally for each piece of data or context (e.g., per-user, per-record)
  2. Encrypt the data with the DEK using AES-256-GCM
  3. Encrypt the DEK with a Key Encryption Key (KEK) stored in KMS
  4. Store the encrypted DEK alongside the encrypted data
  5. To decrypt: fetch the encrypted DEK, call KMS to unwrap it, use the DEK to decrypt data
Plaintext data → [AES-256-GCM with DEK] → Ciphertext
DEK → [KMS: Encrypt with KEK] → Encrypted DEK

Storage: { ciphertext, encrypted_DEK }

Why this pattern?

  • Only small DEKs cross the network to KMS — not large data payloads (faster, cheaper)
  • Rotating the KEK only requires re-encrypting the DEKs, not all the data
  • Revoking access to a KEK effectively destroys all data encrypted under it

KMS Providers

AWS KMS

AWS KMS manages keys via Hardware Security Modules (HSMs) in AWS-operated data centers.

import { KMSClient, EncryptCommand, DecryptCommand, GenerateDataKeyCommand } from '@aws-sdk/client-kms';

const kms = new KMSClient({ region: 'us-east-1' });

// Generate a data key
const { CiphertextBlob, Plaintext } = await kms.send(
  new GenerateDataKeyCommand({
    KeyId: 'arn:aws:kms:us-east-1:123456789012:key/mrk-abc123',
    KeySpec: 'AES_256'
  })
);

// Plaintext is the DEK — use it to encrypt, then immediately discard
// CiphertextBlob is the encrypted DEK — store this alongside your ciphertext

Key policies in AWS KMS control who can use and manage each key:

{
  "Statement": [
    {
      "Sid": "Allow application encryption",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/app-role"
      },
      "Action": ["kms:GenerateDataKey", "kms:Decrypt"],
      "Resource": "*"
    },
    {
      "Sid": "Key administrators cannot decrypt",
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/key-admin-role"
      },
      "Action": "kms:Decrypt",
      "Resource": "*"
    }
  ]
}

Separation of duties: key administrators can manage key lifecycle but cannot decrypt data.

GCP Cloud KMS and Cloud HSM

GCP Cloud KMS integrates natively with GCP services:

# Create a key ring and key
gcloud kms keyrings create my-keyring --location=us-east1
gcloud kms keys create my-key \
  --keyring=my-keyring \
  --location=us-east1 \
  --purpose=encryption \
  --rotation-period=90d \
  --next-rotation-time=$(date -d "+90 days" --iso-8601)

For compliance requirements mandating physical HSM isolation, Cloud HSM provides FIPS 140-2 Level 3 validated key storage.

HashiCorp Vault

Vault is the open-source alternative, suitable for multi-cloud and on-premises environments.

# Enable the transit secrets engine (acts as encryption-as-a-service)
vault secrets enable transit

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

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

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

Vault's Transit engine provides encryption as a service — your application never handles raw encryption keys.

Field-Level Encryption

Database-level encryption (TDE — Transparent Data Encryption) encrypts storage files but decrypts everything for any authorized database connection. Field-level encryption (FLE) goes further: sensitive fields are encrypted before being written to the database, with different keys per field or per tenant.

Use cases:

  • PII fields (SSN, credit card numbers, health data) that only specific application components should decrypt
  • Multi-tenant SaaS where one tenant's data must be cryptographically isolated from another's
  • Audit-proof data access — the database administrator cannot read sensitive fields even with direct DB access

MongoDB Client-Side Field Level Encryption (CSFLE):

import { MongoClient, ClientEncryption } from 'mongodb';

const encryptedFields = {
  fields: [
    {
      path: 'ssn',
      bsonType: 'string',
      algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
    },
    {
      path: 'creditCard',
      bsonType: 'string',
      algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'
    }
  ]
};

Deterministic vs. random encryption:

  • Deterministic — Same plaintext always produces the same ciphertext. Allows equality queries. Use for fields you need to query on.
  • Random — Same plaintext produces different ciphertext each time. No query support but stronger security. Use for fields you only access by primary key.

Key Rotation

Key rotation limits the amount of data encrypted under any single key (limiting the value of compromise) and is a compliance requirement in most frameworks.

Rotation strategies:

  1. Automatic rotation (KEK) — Cloud KMS providers support automatic key rotation. AWS KMS can rotate annual keys automatically; new key material is generated, old material is retained for decryption.
# Enable automatic rotation every 365 days
aws kms enable-key-rotation --key-id arn:aws:kms:us-east-1:123456789012:key/abc
  1. Re-encryption (DEK) — When rotating KEKs, DEKs must be re-encrypted under the new KEK. This is a batch job, not a real-time operation.

  2. Per-data-key rotation — For high-security use cases, generate a new DEK for each write, not just each new user or record type. This limits the data exposed if any single DEK is compromised.

Rotation schedule recommendations:

Key typeRecommended rotation
KMS root keysAnnual (automatic)
Data encryption keysPer-record or quarterly
TLS certificatesAnnual (automatic via cert-manager)
Database credential encryption keys90 days

Encryption for Compliance

GDPR requires "appropriate technical measures" including pseudonymisation and encryption. For right-to-erasure requests, cryptographic erasure — destroying the encryption key for a user's data — can be a valid alternative to physical deletion if implemented correctly.

PCI DSS requires encryption of Primary Account Numbers (PANs) at rest using AES-128 or stronger, with documented key management procedures.

HIPAA does not mandate specific algorithms but recognizes encryption as a "safe harbor" — encrypted PHI lost in a breach does not trigger breach notification if the decryption key was not compromised.

FedRAMP/NIST SP 800-57 requires FIPS 140-2 validated cryptographic modules and mandates specific key lengths: AES-256 for long-term data, RSA-2048 minimum for asymmetric operations.

Common Mistakes

  1. Storing encryption keys next to encrypted data — If both are in the same database, encryption provides no protection against a database breach.

  2. Using AES-ECB mode — ECB produces identical ciphertext for identical plaintext blocks, revealing patterns. Always use AES-GCM or AES-CBC with a random IV.

  3. Not authenticating ciphertext — AES-GCM provides authentication (preventing tampering). AES-CBC without a MAC does not.

  4. Hard-coding keys in source code — Rotate immediately if this happens. Use environment variables as a minimum, KMS as the correct solution.

  5. Encrypting already-encrypted data repeatedly — Applying multiple layers of encryption is not stronger security; it is operational complexity with no benefit.

Encryption at rest is necessary but not sufficient. Combine it with access controls (who can decrypt), audit logging (who did decrypt), and key management (keeping KEKs separate from ciphertext) to provide meaningful data protection.

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.