Encryption Standards
Overview
Encryption is fundamental to MenoTime's security architecture. All data—whether stored on disk, transmitted over networks, or at rest in databases—must be encrypted using industry-standard algorithms and keys managed according to HIPAA requirements.
Golden Rule: Never send or store unencrypted PHI. Encryption is non-negotiable.
Encryption at Rest
Encryption at rest protects data stored on disks, databases, and backups against physical theft or unauthorized access to storage devices.
RDS Database Encryption
All MenoTime RDS instances storing PHI must use encryption at rest.
Standard: AWS RDS encryption with customer-managed KMS keys
Encryption Method: AES-256 (Advanced Encryption Standard with 256-bit keys)
RDS Encryption Configuration
# terraform/rds.tf
resource "aws_db_instance" "menotime_prod" {
identifier = "menotime-prod"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.large"
allocated_storage = 500
# Encryption at rest
storage_encrypted = true
kms_key_id = aws_kms_key.rds_key.arn
# Backup encryption
backup_retention_period = 30
copy_backups_to_region = "us-west-2" # Cross-region backup
# Authentication
db_name = "menotime_prod"
username = "postgres"
password = random_password.rds_password.result
# Network security
publicly_accessible = false
db_subnet_group_name = aws_db_subnet_group.private.name
vpc_security_group_ids = [aws_security_group.rds_prod.id]
# Enhanced monitoring
monitoring_interval = 60
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
enable_cloudwatch_logs_exports = [
"postgresql"
]
}
KMS Key for RDS
# terraform/kms.tf
resource "aws_kms_key" "rds_key" {
description = "KMS key for MenoTime RDS encryption"
deletion_window_in_days = 30
enable_key_rotation = true # Annual rotation
tags = {
Name = "menotime-rds-key"
Environment = "prod"
Classification = "RESTRICTED"
}
}
resource "aws_kms_alias" "rds_key_alias" {
name = "alias/menotime-rds-prod"
target_key_id = aws_kms_key.rds_key.key_id
}
# Key policy: Allow RDS service and authorized IAM users
resource "aws_kms_key_policy" "rds_key_policy" {
key_id = aws_kms_key.rds_key.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM policies"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::ACCOUNT_ID:root"
}
Action = "kms:*"
Resource = "*"
},
{
Sid = "Allow RDS to use key"
Effect = "Allow"
Principal = {
Service = "rds.amazonaws.com"
}
Action = [
"kms:Decrypt",
"kms:CreateGrant",
"kms:DescribeKey"
]
Resource = "*"
},
{
Sid = "Allow CloudWatch Logs"
Effect = "Allow"
Principal = {
Service = "logs.amazonaws.com"
}
Action = [
"kms:Decrypt",
"kms:GenerateDataKey"
]
Resource = "*"
}
]
})
}
Verify RDS Encryption
# Check if encryption is enabled
aws rds describe-db-instances \
--db-instance-identifier menotime-prod \
--query 'DBInstances[0].StorageEncrypted'
# Output: true
# Check KMS key used
aws rds describe-db-instances \
--db-instance-identifier menotime-prod \
--query 'DBInstances[0].KmsKeyId'
# Output: arn:aws:kms:us-east-1:ACCOUNT_ID:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
S3 Bucket Encryption
All S3 buckets storing PHI or Confidential data must use server-side encryption.
Standard: AWS KMS with customer-managed keys (not S3-managed keys)
S3 Encryption Configuration
# terraform/s3.tf
resource "aws_s3_bucket" "menotime_data" {
bucket = "menotime-prod-data"
tags = {
Name = "MenoTime Production Data"
Classification = "RESTRICTED"
Environment = "prod"
}
}
# Block all public access
resource "aws_s3_bucket_public_access_block" "menotime_data" {
bucket = aws_s3_bucket.menotime_data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Enable versioning (for data recovery)
resource "aws_s3_bucket_versioning" "menotime_data" {
bucket = aws_s3_bucket.menotime_data.id
versioning_configuration {
status = "Enabled"
}
}
# Enable encryption at rest with KMS
resource "aws_s3_bucket_server_side_encryption_configuration" "menotime_data" {
bucket = aws_s3_bucket.menotime_data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3_key.arn
}
bucket_key_enabled = true
}
}
# Enforce encrypted uploads only
resource "aws_s3_bucket_policy" "menotime_data_encryption" {
bucket = aws_s3_bucket.menotime_data.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyUnencryptedObjectUploads"
Effect = "Deny"
Principal = "*"
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.menotime_data.arn}/*"
Condition = {
StringNotEquals = {
"s3:x-amz-server-side-encryption" = "aws:kms"
}
}
},
{
Sid = "DenyInsecureTransport"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.menotime_data.arn,
"${aws_s3_bucket.menotime_data.arn}/*"
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
}
]
})
}
EBS Volume Encryption
All EC2 instances storing temporary data must use encrypted EBS volumes.
# terraform/ec2.tf
resource "aws_instance" "menotime_app" {
# ... instance configuration ...
root_block_device {
delete_on_termination = true
encrypted = true
kms_key_id = aws_kms_key.ebs_key.arn
volume_size = 100
volume_type = "gp3"
}
ebs_block_device {
device_name = "/dev/sdf"
volume_size = 200
volume_type = "gp3"
encrypted = true
kms_key_id = aws_kms_key.ebs_key.arn
delete_on_termination = true
}
}
Secrets Manager Encryption
All secrets stored in AWS Secrets Manager are automatically encrypted at rest with KMS.
# terraform/secrets.tf
resource "aws_secretsmanager_secret" "rds_password" {
name = "menotime/prod/rds/password"
description = "RDS database password for MenoTime production"
kms_key_id = aws_kms_key.secrets_key.id
recovery_window_in_days = 7
tags = {
Environment = "prod"
Classification = "RESTRICTED"
}
}
resource "aws_secretsmanager_secret_version" "rds_password" {
secret_id = aws_secretsmanager_secret.rds_password.id
secret_string = jsonencode({
username = "postgres"
password = random_password.rds_password.result
host = aws_db_instance.menotime_prod.endpoint
port = 5432
dbname = "menotime_prod"
})
}
Encryption in Transit
Encryption in transit (also called "encryption in motion") protects data as it travels across networks, preventing interception by attackers.
TLS/HTTPS Standards
All communication with MenoTime systems must use TLS 1.2 or higher. TLS 1.0 and 1.1 are deprecated and prohibited.
Standard: TLS 1.2 minimum; TLS 1.3 preferred
Cipher Suites: ECDHE with AES-GCM (perfect forward secrecy required)
Application Server Configuration
Example: Node.js/Express HTTPS configuration
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
// Load TLS certificate and private key
const options = {
key: fs.readFileSync('/etc/ssl/private/key.pem'),
cert: fs.readFileSync('/etc/ssl/certs/cert.pem'),
// Enforce TLS 1.2 minimum
minVersion: 'TLSv1.2',
// Recommended cipher suites
ciphers: [
'ECDHE-ECDSA-AES256-GCM-SHA384',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-ECDSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES128-GCM-SHA256',
].join(':'),
// Enforce server cipher order
honorCipherOrder: true,
};
https.createServer(options, app).listen(443);
Example: HSTS Header (enforce HTTPS in browsers)
// Require HTTPS everywhere
app.use((req, res, next) => {
if (req.secure) {
next();
} else {
res.redirect(`https://${req.headers.host}${req.url}`);
}
});
// HSTS header: enforce HTTPS for 1 year
app.use((req, res, next) => {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
next();
});
Database Connection Encryption
PostgreSQL: Require SSL Connection
-- Force SSL connections for all users
ALTER SYSTEM SET ssl = on;
ALTER SYSTEM SET ssl_cert_file = '/etc/ssl/certs/server.crt';
ALTER SYSTEM SET ssl_key_file = '/etc/ssl/private/server.key';
-- Require SSL for user connections
ALTER USER menotime_app WITH PASSWORD 'password' CREATEDB;
-- Force SSL enforcement
-- In pg_hba.conf:
# TYPE DATABASE USER ADDRESS METHOD
hostssl menotime all 0.0.0.0/0 scram-sha-256
hostssl menotime all ::/0 scram-sha-256
Application Connection String (SSL required)
postgresql://menotime_user:password@menotime-prod.cluster-xxx.us-east-1.rds.amazonaws.com:5432/menotime_prod?sslmode=require&sslrootcert=/path/to/rds-ca-bundle.pem
VPN for Database Access
Remote access to databases must use a corporate VPN with encryption.
# OpenVPN configuration
# /etc/openvpn/client.conf
client
proto tcp
remote vpn.timelessbiotech.com 443
cipher AES-256-GCM
auth SHA256
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
File Transfer Encryption
Healthcare providers and staff must use encrypted file transfer methods.
Approved Methods: - ✓ SFTP (SSH File Transfer Protocol) - ✓ HTTPS file download (from secure link) - ✓ AWS S3 with HTTPS and KMS encryption - ✓ Encrypted email (though not recommended)
Prohibited Methods: - ✗ FTP (unencrypted) - ✗ Unencrypted HTTP - ✗ Unencrypted email attachments - ✗ Shared cloud storage (Google Drive, Dropbox) without encryption
SFTP Configuration
# SSH server configuration for SFTP
# /etc/ssh/sshd_config
Port 22
AddressFamily any
Protocol 2
# TLS/SSH version
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
# Key exchange
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
# MAC algorithms
MACs umac-128-etm@openssh.com,hmac-sha2-256
# Require strong key exchange
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# SFTP subsystem
Subsystem sftp /usr/lib/openssh/sftp-server
Using SFTP for Secure File Transfer
# Upload file to SFTP server
sftp healthcare-provider@sftp.timelessbiotech.com
sftp> put patient_data.csv.gpg /incoming/
# Download file from SFTP server
sftp> get /outgoing/results.csv.gpg results.csv.gpg
sftp> quit
# Verify file integrity with checksum
sha256sum results.csv.gpg
Email Encryption
PHI must never be transmitted via email, but if necessary, emails must be encrypted.
Approved Email Methods: - ✓ S/MIME encryption (certificate-based) - ✓ Pretty Good Privacy (PGP/GPG) - ✓ Secure email gateway (with TLS)
Prohibited: - ✗ Unencrypted email - ✗ Email with PHI in body text - ✗ Email with PHI in subject line
S/MIME Configuration (Outlook/Gmail)
- Obtain digital certificate from Timeless Biotech IT
- Import certificate into email client
- Enable "Encrypt this message" before sending
- Recipient must have their certificate to decrypt
Better Alternative: Secure File Link
Subject: Secure File Download Link
Dear Provider,
Your requested patient data is ready. Please download from the secure link below:
Link: https://sftp.timelessbiotech.com/secure/download?token=xyz123
Password: [sent separately via phone]
Expiration: 72 hours
This is more secure than email encryption.
Key Management
Encryption keys themselves must be protected and managed carefully.
KMS Key Rotation
AWS KMS automatically rotates customer-managed keys annually (every 365 days). Manual rotation can be triggered anytime.
# Check key rotation status
aws kms get-key-rotation-status \
--key-id arn:aws:kms:us-east-1:ACCOUNT_ID:key/xxxxxxxx
# Output: { "KeyRotationEnabled": true }
# Manually rotate a key (creates new key version)
aws kms rotate-key-in-place \
--key-id arn:aws:kms:us-east-1:ACCOUNT_ID:key/xxxxxxxx
KMS Key Policies
Access to KMS keys is controlled via key policies. Only authorized users and services can use keys for encryption/decryption.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM Root Account",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow RDS Service",
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow CloudWatch Logs",
"Effect": "Allow",
"Principal": {
"Service": "logs.amazonaws.com"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*"
},
{
"Sid": "Allow Application IAM Role",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:role/menotime-app-role"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*"
}
]
}
Certificate Management
TLS certificates must be managed and renewed before expiration.
Certificate Management Process:
- Certificate source: AWS Certificate Manager (ACM) for simplicity
- Validation: Domain validation (AWS handles automatically for new certificates)
- Renewal: ACM auto-renews 60 days before expiration
- Monitoring: CloudWatch alerts for expiration
- Deployment: Automatic deployment to load balancers and CloudFront
Monitoring Certificate Expiration
# terraform/certificates.tf
resource "aws_acm_certificate" "menotime" {
domain_name = "api.timelessbiotech.com"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
tags = {
Name = "menotime-api-cert"
}
}
# CloudWatch alarm: alert if certificate expires in 30 days
resource "aws_cloudwatch_metric_alarm" "cert_expiration" {
alarm_name = "menotime-cert-expiration"
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "DaysToExpiry"
namespace = "AWS/CertificateManager"
period = 86400
statistic = "Minimum"
threshold = 30
alarm_actions = [aws_sns_topic.security_alerts.arn]
}
Encryption Standards by Use Case
Encrypting Sensitive Documents
Recommended: AES-256 using OpenSSL
# Encrypt a file with AES-256
openssl enc -aes-256-cbc -in patient_data.csv -out patient_data.csv.enc -k [password]
# Decrypt the file
openssl enc -d -aes-256-cbc -in patient_data.csv.enc -out patient_data.csv -k [password]
Encrypting Database Backups
All RDS backups are automatically encrypted with the KMS key assigned to the database.
# Create manual snapshot (will be encrypted)
aws rds create-db-snapshot \
--db-instance-identifier menotime-prod \
--db-snapshot-identifier menotime-prod-backup-$(date +%Y%m%d)
# List encrypted snapshots
aws rds describe-db-snapshots \
--query "DBSnapshots[?StorageEncrypted==`true`]"
Encrypting Data in Code/Configuration
Never commit unencrypted sensitive data to Git. Use Secrets Manager or encrypted files.
Option 1: AWS Secrets Manager (Recommended)
import boto3
import json
client = boto3.client('secretsmanager')
secret = client.get_secret_value(SecretId='menotime/prod/rds/password')
credentials = json.loads(secret['SecretString'])
Option 2: Encrypted .env Files
# Encrypt .env file
gpg --symmetric --cipher-algo AES256 .env.prod
# Decrypt when needed
gpg --decrypt .env.prod.gpg > .env.prod
# Load variables
source .env.prod
Compliance Checklist
- ✓ All RDS instances encrypted at rest with customer-managed KMS keys
- ✓ All S3 buckets with Confidential/Restricted data encrypted with KMS
- ✓ All EBS volumes encrypted with KMS
- ✓ All Secrets Manager secrets encrypted with KMS
- ✓ All data in transit uses TLS 1.2 or higher
- ✓ TLS certificates valid and monitored for expiration
- ✓ KMS key rotation enabled (annual minimum)
- ✓ Key policies restrict access to authorized services and users
- ✓ All SFTP connections use SSH with strong ciphers
- ✓ VPN required for remote database access
- ✓ Encryption keys never committed to Git or shared
- ✓ No plaintext credentials in application code
- ✓ All backups encrypted with KMS
- ✓ Certificate monitoring and auto-renewal enabled
Questions? Contact the Security Officer at security@timelessbiotech.com.