HIPAA-02: Encryption at Rest — Key Isolation Finding & Remediation
HIPAA-02: Encryption at Rest — Key Isolation
Compliance Control: HIPAA-02
Framework: HIPAA
Affected File:src/lib/encryption.ts
Status: Finding identified — remediation in progress
Overview
This document describes a key isolation deficiency identified in the platform's encryption-at-rest implementation, the associated compliance risk under HIPAA-02, and the planned remediation approach.
The Problem
Single Key for All Data Domains
The current implementation derives one encryption key from a single ENCRYPTION_SECRET environment variable using PBKDF2. Every encrypted field in the platform — regardless of PII category — uses this same derived key material.
ENCRYPTION_SECRET
│
PBKDF2 (static salt: 'calmony-sanctions-monitor-v1')
│
Single derived key
│
┌────┴────────────────────────┐
│ names │ phone numbers │ … │
└─────────────────────────────┘
Hardcoded Static Salt
The PBKDF2 derivation uses a salt that is hardcoded in source:
calmony-sanctions-monitor-v1
A static salt means the key derivation is fully deterministic given the secret alone — there is no per-call or per-domain randomness.
Compliance Risk
| Risk | Detail |
|---|---|
| Blast radius | Compromising ENCRYPTION_SECRET exposes all encrypted PII simultaneously, across every data domain. |
| No domain separation | An attacker who recovers the key for one field type (e.g. phone numbers) can decrypt all other field types. |
| HIPAA-02 non-conformance | HIPAA-02 requires appropriate safeguards to protect the confidentiality of ePHI, including limiting exposure in the event of a key compromise. |
Recommended Remediation
Step 1 — Per-Domain Key Derivation (Short-Term)
Introduce a context parameter into the key derivation function so that each PII domain produces distinct key material:
// Instead of a single derived key:
deriveKey(secret: string): CryptoKey
// Use a context-aware derivation:
deriveKey(secret: string, context: string): CryptoKey
Example context strings:
const CONTEXTS = {
names: 'names-v1',
phoneNumbers: 'phone-numbers-v1',
// add new domains here
};
This approach:
- Requires no additional secrets — the single
ENCRYPTION_SECRETremains the root. - Provides cryptographic domain separation — key material for
names-v1is mathematically independent fromphone-numbers-v1. - Limits blast radius — a compromised context-specific key does not expose other domains.
- Is backward-compatible via a migration path: re-encrypt existing records with the new derived keys.
Step 2 — Managed Key Service (Long-Term)
For production deployments handling real ePHI, migrate to a dedicated key management service:
| Option | Notes |
|---|---|
| AWS KMS | Per-key IAM policies, automatic rotation, CloudTrail audit log |
| GCP Cloud KMS | Per-key IAM, Cloud Audit Logs, supports envelope encryption |
Both services provide true key isolation, hardware-backed key storage, and the audit trails required by HIPAA's technical safeguard rules.
Migration Considerations
When per-domain key derivation is implemented, existing encrypted records will need to be re-encrypted:
- Decrypt each record using the old single derived key.
- Re-encrypt using the new context-specific derived key.
- Store the new ciphertext.
This migration should be performed in a transaction or with a dual-read fallback to avoid data loss during rollover.
Environment Variables
| Variable | Purpose |
|---|---|
ENCRYPTION_SECRET | Root secret used for PBKDF2 key derivation. Must be kept confidential. Rotate immediately if compromised. |
Note: The static salt
calmony-sanctions-monitor-v1is hardcoded insrc/lib/encryption.ts. After implementing per-domain derivation, consider also making the base salt configurable or randomly generated per-record where the threat model warrants it.
References
- HIPAA Security Rule — 45 CFR § 164.312(a)(2)(iv): Encryption and Decryption
- HIPAA Security Rule — 45 CFR § 164.312(e)(2)(ii): Encryption of ePHI in transit
- NIST SP 800-132: Recommendation for Password-Based Key Derivation
- AWS KMS Documentation
- GCP Cloud KMS Documentation