Data Encryption Policy
Data Encryption Policy
Project / Organization: {{ORG_NAME}} Policy Number: POL-SEC-{{NUMBER}} Version: {{VERSION}} Date: {{DATE}} Author: {{AUTHOR}} Status: Draft | In Review | Approved Reviewers: {{REVIEWERS}} Next Review: {{REVIEW_DATE}} Classification: Confidential
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | {{DATE}} | {{AUTHOR}} | Initial draft |
1. Purpose & Scope
Purpose: This policy defines the minimum encryption standards for data at rest, in transit, and at the application level across all systems operated by {{ORG_NAME}}.
Scope: This policy applies to:
- All systems, applications, and infrastructure operated by {{ORG_NAME}}
- All employees, contractors, and third parties with access to {{ORG_NAME}} systems
- All data classified as Internal, Confidential, or Restricted (see compliance-framework.md §5)
- All cloud environments, on-premises systems, and developer workstations
Exceptions: Public-facing static content (HTML, CSS, JS files, public images) does not require encryption at rest beyond transport layer security.
2. Encryption Standards & Approved Algorithms
2.1 Approved Algorithms
Symmetric Encryption
| Use Case | Algorithm | Key Size | Mode | Notes |
|---|---|---|---|---|
| Data at rest (general) | AES | 256-bit | GCM | Authenticated encryption — preferred |
| Data at rest (legacy/interop) | AES | 256-bit | CBC | Only with HMAC-SHA-256 for integrity |
| Stream encryption | ChaCha20-Poly1305 | 256-bit | — | Alternative to AES on non-AES-NI hardware |
| File encryption | AES | 256-bit | GCM | With random 96-bit IV per file |
Asymmetric Encryption
| Use Case | Algorithm | Key Size | Notes |
|---|---|---|---|
| Key exchange / TLS | ECDHE | P-256 / P-384 | Prefer P-384 for Confidential/Restricted data |
| Digital signatures | Ed25519 | 256-bit | Preferred for new systems |
| Digital signatures (legacy) | RSA | 4096-bit | Only where Ed25519 not supported |
| Code signing | Ed25519 | 256-bit | All release artifacts |
| Certificate signing | RSA | 4096-bit | For CA certificates only |
| Encryption (hybrid) | RSA-OAEP | 4096-bit | Encrypt DEK with RSA when ECC not available |
Hashing & Password Storage
| Use Case | Algorithm | Parameters | Notes |
|---|---|---|---|
| Password hashing | Argon2id | m=65536, t=3, p=4 | Preferred for new systems |
| Password hashing (legacy) | bcrypt | cost factor ≥ 12 | Acceptable if Argon2 not available |
| Data integrity (general) | SHA-256 | — | For non-security-critical hashing |
| HMAC (message auth) | HMAC-SHA-256 | — | For webhook signatures, API tokens |
| File integrity | SHA-256 | — | For artifact verification |
| Token derivation | HKDF-SHA-256 | — | For deriving keys from master key |
2.2 Prohibited Algorithms (NEVER USE)
| Algorithm | Reason | Migration Required By |
|---|---|---|
| MD5 | Collision attacks (2004+) | Already prohibited |
| SHA-1 | Collision attacks (2017+) | Already prohibited |
| DES / 3DES | Key size insufficient | Already prohibited |
| RC4 | Statistical biases | Already prohibited |
| ECB mode (any cipher) | Leaks data patterns | Already prohibited |
| RSA < 2048-bit | Insufficient key strength | Already prohibited |
| AES-128 (Restricted data) | Insufficient for Restricted classification | Upgrade by {{DATE}} |
3. Encryption at Rest
3.1 Database Encryption
| Database | Method | Key Management | Classification Coverage |
|---|---|---|---|
| PostgreSQL (primary) | TDE via cloud provider (AES-256) | Cloud KMS | All classifications |
| PostgreSQL (field-level PII) | AES-256-GCM at application layer | Application KMS key | Confidential / Restricted |
| Redis | Cloud provider encryption (AES-256) | Cloud KMS | Internal / Confidential |
| Elasticsearch | AES-256 (X-Pack security) | Cloud KMS | Internal |
Implementation pattern (field-level):
// Envelope encryption for PII fields
async function encryptField(plaintext: string): Promise<string> {
// 1. Generate random DEK
const dek = crypto.randomBytes(32);
// 2. Encrypt DEK with KEK from KMS
const encryptedDek = await kmsClient.encrypt({ KeyId: KEK_ARN, Plaintext: dek });
// 3. Encrypt data with DEK
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', dek, iv);
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
const tag = cipher.getAuthTag();
// 4. Return: base64(encryptedDek || iv || tag || ciphertext)
return Buffer.concat([encryptedDek, iv, tag, ciphertext]).toString('base64');
}
3.2 File / Object Storage Encryption
| Storage | Method | Key Management | Notes |
|---|---|---|---|
| S3 / GCS / Azure Blob | SSE-KMS (AES-256) | Cloud KMS — per-bucket key | |
| Backup files | AES-256-GCM | Separate backup KMS key | Keys in different account |
| Developer local storage | OS-level full disk encryption | Platform key (FileVault / BitLocker) | Required for all devices |
| USB / portable media | AES-256 | Password + AES-256 | Prohibited for Restricted data |
3.3 Backup Encryption
All backups MUST be encrypted before transfer off primary system.
pg_dump | gzip | gpg --encrypt --recipient {{BACKUP_KEY_ID}} > backup.sql.gz.gpg
Backup encryption key: Stored in separate KMS region from primary
Backup key rotation: Annual
Backup key escrow: Stored with {{ESCROW_LOCATION}}
4. Encryption in Transit
4.1 TLS Configuration Standards
Minimum TLS version:
- External-facing services: TLS 1.2 (TLS 1.3 preferred)
- Internal service-to-service: TLS 1.3 (enforced)
- Legacy system support: Documented exception required
Approved cipher suites (TLS 1.3):
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256 (minimum — prefer 256)
Approved cipher suites (TLS 1.2 — for backwards compatibility only):
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-CHACHA20-POLY1305
ECDHE-RSA-CHACHA20-POLY1305
Prohibited TLS configurations:
- TLS 1.0 and TLS 1.1 — prohibited
- SSL 2.0 / SSL 3.0 — prohibited
- RC4 cipher suites — prohibited
- Export-grade cipher suites — prohibited
- NULL cipher suites — prohibited
- Anonymous DH cipher suites — prohibited
4.2 Certificate Management
| Certificate Type | Validity | Authority | Rotation | Monitoring |
|---|---|---|---|---|
| External TLS (*.{{DOMAIN}}) | 90 days | Let's Encrypt / {{CA}} | Automated (cert-manager) | Alert 30 days before expiry |
| Internal service TLS | 30 days | Internal CA ({{TOOL}}) | Automated | Alert 7 days before expiry |
| Code signing | 1 year | {{CA}} | Manual | Calendar reminder |
| Root CA | 10 years | Self-signed | Manual | Calendar reminder |
Certificate monitoring: {{CERT_MONITORING_TOOL}} — alert channel: #security-alerts
4.3 mTLS for Internal Service Communication
All service-to-service calls within the cluster MUST use mTLS.
Implementation: {{ISTIO / LINKERD / cert-manager / custom}}
Certificate generation: SPIFFE/SVID standard
Rotation: Every {{ROTATION_PERIOD}} — automated via sidecar
Verification: Server verifies client cert against trusted CA
Service identity: SPIFFE URI (e.g., spiffe://{{TRUST_DOMAIN}}/ns/{{NS}}/sa/{{SERVICE_ACCOUNT}})
5. Application-Level Encryption
5.1 Field-Level Encryption
When required: All fields classified as Restricted (L4) must be encrypted at the application layer, in addition to database-level encryption.
Fields requiring field-level encryption:
| Field | Table | Classification | Key |
|---|---|---|---|
mfa_secret |
users |
Restricted | USER_MFA_KEY |
{{PII_FIELD}} |
{{TABLE}} |
Confidential | USER_PII_KEY |
api_key_secret |
api_keys |
Restricted | API_KEY_KEY |
{{FINANCIAL_FIELD}} |
{{TABLE}} |
Restricted | FINANCIAL_KEY |
5.2 Envelope Encryption
Master Key (KEK) — stored in KMS, never loaded into application memory
↓ (KMS encrypt operation)
Data Encryption Key (DEK) — generated per record/session, encrypted by KEK
↓ (application encrypt operation — AES-256-GCM)
Data — encrypted at rest, decrypted only on read
DEK lifetime:
- Per-session DEKs: lifetime of session
- Per-record DEKs: same as record (stored encrypted alongside data)
- Bulk DEKs: rotate every {{ROTATION_PERIOD}}
5.3 Tokenization
What is tokenized: Payment card data, bank account numbers Implementation: {{PAYMENT_PROVIDER}} handles tokenization — we store tokens only Format-preserving encryption: {{YES/NO}} — {{TOOL}} for {{USE_CASE}}
6. Key Management
Full policy: key-management-policy.md
Summary
| Key Type | KMS | Rotation | Owner |
|---|---|---|---|
| Master encryption keys (KEKs) | {{KMS_TOOL}} | Annual | Security team |
| Data encryption keys (DEKs) | Application-managed | Per rotation policy | Engineering |
| TLS certificates | cert-manager | 90 days / 30 days | Platform |
| API signing keys | {{KMS_TOOL}} | Quarterly | Security team |
| Backup encryption keys | {{KMS_TOOL}} (separate region) | Annual | Security team |
7. Cryptographic Inventory
| System | Algorithm | Key Size | Mode | Key Location | Last Rotated | Next Rotation |
|---|---|---|---|---|---|---|
| PostgreSQL TDE | AES-256 | 256-bit | XTS | Cloud KMS | {{DATE}} | {{DATE}} |
| User PII field encryption | AES-256-GCM | 256-bit | GCM | App KMS | {{DATE}} | {{DATE}} |
| External TLS | ECDSA P-256 | 256-bit | GCM | cert-manager | {{DATE}} | {{DATE}} |
| Internal TLS (mTLS) | Ed25519 | 256-bit | — | cert-manager | {{DATE}} | {{DATE}} |
| Password hashing | Argon2id | m=65536,t=3 | — | N/A | N/A | N/A |
| API key hashing | HMAC-SHA-256 | 256-bit | — | App secrets | {{DATE}} | {{DATE}} |
| S3 bucket encryption | AES-256 (SSE-KMS) | 256-bit | — | Cloud KMS | {{DATE}} | Annual |
8. Algorithm Deprecation Schedule
| Algorithm | Current Usage | Deprecation Date | Migration Target | Migration Owner | Status |
|---|---|---|---|---|---|
| RSA-2048 (old API keys) | {{N}} keys | {{DATE}} | RSA-4096 or Ed25519 | Engineering | In progress |
| AES-128 ({{SYSTEM}}) | {{USAGE}} | {{DATE}} | AES-256 | Engineering | TODO |
| bcrypt cost < 12 | Legacy user hashes | {{DATE}} | Argon2id | Engineering | TODO |
| SHA-256 (Restricted data) | {{USAGE}} | {{DATE}} | SHA-384 | Engineering | TODO |
9. Exception Process
Exceptions are not permitted for: Restricted (L4) data — no exceptions.
Exception request process:
- Submit exception request to: {{SECURITY_TEAM_EMAIL}}
- Required information:
- System and data classification affected
- Algorithm/standard being excepted from
- Business justification
- Risk assessment
- Compensating controls
- Proposed exception duration (max 12 months)
- Approval required from: CISO
- Exceptions logged in: {{EXCEPTION_REGISTER_LOCATION}}
- Review: Quarterly — exceptions that cannot be remediated within 12 months require board-level approval
Active exceptions:
| System | Exception | Expiry | Compensating Controls |
|---|---|---|---|
| {{LEGACY_SYSTEM}} | TLS 1.2 (TLS 1.3 not supported) | {{DATE}} | Isolated network segment + IDS monitoring |
Approval
| Role | Name | Date | Signature |
|---|---|---|---|
| Author | |||
| CISO | |||
| CTO | |||
| DPO (GDPR relevance) | |||
| Management |