Skip to content

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)

  1. Obtain digital certificate from Timeless Biotech IT
  2. Import certificate into email client
  3. Enable "Encrypt this message" before sending
  4. 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:

  1. Certificate source: AWS Certificate Manager (ACM) for simplicity
  2. Validation: Domain validation (AWS handles automatically for new certificates)
  3. Renewal: ACM auto-renews 60 days before expiration
  4. Monitoring: CloudWatch alerts for expiration
  5. 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.