| name | cryptography-policy |
| description | Cryptographic controls implementation: TLS 1.3, AES-256-GCM, bcrypt, RSA-4096, key management per NIST FIPS 140-2 and ISO 27001 A.8.24 |
Cryptography Policy Skill
Purpose
This skill establishes cryptographic standards and implementation patterns for the CIA platform, ensuring proper encryption of data at rest, in transit, and in processing. It demonstrates professional cryptographic practices aligned with NIST FIPS 140-2, ISO 27001 A.8.24, and Hack23 ISMS Cryptography Policy.
When to Use This Skill
Apply this skill when:
- ✅ Implementing encryption for sensitive data storage
- ✅ Configuring TLS/SSL for network communication
- ✅ Managing cryptographic keys and certificates
- ✅ Implementing password hashing and authentication
- ✅ Designing secure API authentication mechanisms
- ✅ Configuring AWS encryption services (KMS, S3, RDS)
- ✅ Implementing digital signatures or message authentication
- ✅ Conducting cryptographic compliance audits
Do NOT use for:
- ❌ Encoding/decoding (Base64, URL encoding - not encryption)
- ❌ Compression (gzip, zip - not security)
- ❌ Obfuscation (code minification - not cryptography)
Decision Tree
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#1565C0',
'primaryTextColor': '#fff',
'lineColor': '#1565C0',
'secondaryColor': '#7B1FA2',
'tertiaryColor': '#4CAF50'
}
}
}%%
flowchart TD
START["🔒 Cryptography Need"] --> TYPE{"📊 Data State?"}
TYPE -->|At Rest| REST["💾 Data at Rest<br/>Storage Encryption"]
TYPE -->|In Transit| TRANSIT["🌐 Data in Transit<br/>TLS/HTTPS"]
TYPE -->|In Use| USE["🔐 Data in Use<br/>Application Encryption"]
REST --> CLASS{"🏷️ Data Classification?"}
TRANSIT --> PROTOCOL{"📡 Protocol?"}
USE --> ALGO{"🔑 Algorithm Type?"}
CLASS -->|Extreme/High| AES256["🔐 AES-256-GCM<br/>Customer Managed Keys"]
CLASS -->|Standard/Low| AES128["🔐 AES-256<br/>Service Managed Keys"]
PROTOCOL -->|Web/API| HTTPS["🌐 HTTPS/TLS 1.3<br/>Strong Ciphers"]
PROTOCOL -->|Database| DBSSL["🗄️ Database SSL/TLS<br/>PostgreSQL SSL"]
PROTOCOL -->|Email| SMTPTLS["📧 SMTP + TLS<br/>S/MIME Optional"]
ALGO -->|Symmetric| SYM["🔐 AES-256-GCM<br/>Authenticated Encryption"]
ALGO -->|Asymmetric| ASYM["🔑 RSA-4096 or Ed25519<br/>Public Key Crypto"]
ALGO -->|Hashing| HASH[#️⃣ SHA-256 or bcrypt<br/>Secure Hashing]
AES256 --> KMS["🔑 AWS KMS<br/>Key Management"]
AES128 --> KMS
SYM --> KMS
ASYM --> KEYSTORE["🏦 Key Storage<br/>HSM or Secrets Manager"]
HASH --> IMPL["✅ Implementation"]
HTTPS --> TLS["✅ TLS Configuration"]
DBSSL --> TLS
SMTPTLS --> TLS
KMS --> ROTATION["🔄 Key Rotation<br/>Annual Minimum"]
KEYSTORE --> ROTATION
TLS --> CERT["📜 Certificate Management<br/>90-day Renewal"]
ROTATION --> AUDIT["📊 Audit Logging<br/>All Key Operations"]
CERT --> AUDIT
IMPL --> AUDIT
style START fill:#1565C0,color:#fff
style AES256 fill:#7B1FA2,color:#fff
style HTTPS fill:#4CAF50,color:#fff
style KMS fill:#FF9800,color:#fff
style AUDIT fill:#4CAF50,color:#fff
Approved Cryptographic Algorithms
Symmetric Encryption
✅ APPROVED: AES (Advanced Encryption Standard)
Algorithm: AES
Key_Sizes:
- 256-bit (Preferred)
- 192-bit (Acceptable)
- 128-bit (Legacy support only)
Modes:
Recommended:
- GCM (Galois/Counter Mode): Authenticated encryption
- CCM (Counter with CBC-MAC): Authenticated encryption
Acceptable_with_Caution:
- CBC (Cipher Block Chaining): Requires HMAC for authentication
- CTR (Counter Mode): Requires HMAC for authentication
PROHIBITED:
- ECB (Electronic Codebook): Insecure, deterministic
- OFB, CFB: Use GCM or CCM instead
Use_Cases:
- Database encryption (RDS, PostgreSQL)
- File encryption (S3, EBS volumes)
- Application-level encryption
- Session data encryption
Java Implementation:
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class SecureEncryption {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
private static final int KEY_SIZE = 256;
private static final int GCM_IV_LENGTH = 12;
private static final int GCM_TAG_LENGTH = 128;
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
keyGenerator.init(KEY_SIZE, new SecureRandom());
return keyGenerator.generateKey();
}
public static byte[] encrypt(byte[] plaintext, SecretKey key) throws Exception {
byte[] iv = new byte[GCM_IV_LENGTH];
new SecureRandom().nextBytes(iv);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] ciphertext = cipher.doFinal(plaintext);
byte[] encrypted = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, iv.length);
System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length);
return encrypted;
}
public static byte[] decrypt(byte[] encrypted, SecretKey key) throws Exception {
byte[] iv = new byte[GCM_IV_LENGTH];
System.arraycopy(encrypted, 0, iv, 0, iv.length);
byte[] ciphertext = new byte[encrypted.length - GCM_IV_LENGTH];
System.arraycopy(encrypted, GCM_IV_LENGTH, ciphertext, 0, ciphertext.length);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
return cipher.doFinal(ciphertext);
}
}
❌ PROHIBITED: DES, 3DES, RC4
Deprecated_Algorithms:
DES:
Reason: 56-bit key length insufficient
Replacement: AES-256
Deadline: Immediate removal required
3DES:
Reason: Block size vulnerability (Sweet32)
Replacement: AES-256
Deadline: Migrate by end of 2025
RC4:
Reason: Multiple cryptographic weaknesses
Replacement: AES-GCM or ChaCha20-Poly1305
Deadline: Immediate removal required
Asymmetric Encryption
✅ APPROVED: RSA
Algorithm: RSA
Key_Sizes:
- 4096-bit (Preferred for long-term keys)
- 3072-bit (Acceptable)
- 2048-bit (Minimum, legacy support only)
Padding_Schemes:
Encryption:
- OAEP (Optimal Asymmetric Encryption Padding) with SHA-256
Signature:
- PSS (Probabilistic Signature Scheme) with SHA-256
PROHIBITED_Padding:
- PKCS#1 v1.5: Vulnerable to padding oracle attacks
Use_Cases:
- SSH keys (prefer Ed25519)
- TLS certificates (prefer ECDSA)
- Data encryption for small payloads
- Digital signatures
Java Implementation:
import java.security.*;
import javax.crypto.Cipher;
import java.security.spec.RSAKeyGenParameterSpec;
public class RSASecureEncryption {
private static final int KEY_SIZE = 4096;
private static final String ALGORITHM = "RSA";
private static final String TRANSFORMATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
private static final String SIGNATURE_ALGORITHM = "SHA256withRSA/PSS";
public static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(KEY_SIZE, new SecureRandom());
return keyGen.generateKeyPair();
}
public static byte[] encrypt(byte[] plaintext, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(plaintext);
}
public static byte[] decrypt(byte[] ciphertext, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(ciphertext);
}
public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static boolean verify(byte[] data, byte[] signatureBytes, PublicKey publicKey)
throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(signatureBytes);
}
}
✅ APPROVED: Elliptic Curve Cryptography (ECC)
Algorithm: ECDSA / ECDH
Curves:
Preferred:
- Ed25519 (EdDSA signatures)
- X25519 (ECDH key exchange)
- P-384 (NIST curve for FIPS compliance)
Acceptable:
- P-256 (secp256r1, prime256v1)
PROHIBITED:
- P-192: Insufficient security margin
- Custom curves: Avoid unless peer-reviewed
Use_Cases:
- SSH keys (Ed25519 preferred)
- TLS certificates (ECDSA preferred over RSA)
- JWT signatures
- Cryptocurrency/blockchain applications
SSH Key Generation Example:
ssh-keygen -t ed25519 -C "user@cia.hack23.com" -f ~/.ssh/id_ed25519
ssh-keygen -t ecdsa -b 384 -C "user@cia.hack23.com" -f ~/.ssh/id_ecdsa
ssh-keygen -t rsa -b 4096 -C "user@cia.hack23.com" -f ~/.ssh/id_rsa
ssh-keygen -lf ~/.ssh/id_ed25519.pub
Cryptographic Hashing
✅ APPROVED: SHA-2 Family
Algorithms:
SHA-256:
Output: 256 bits
Use: General purpose, integrity verification
Status: Approved
SHA-384:
Output: 384 bits
Use: Higher security margin required
Status: Approved
SHA-512:
Output: 512 bits
Use: Long-term security, high-security applications
Status: Approved
Use_Cases:
- File integrity verification
- Digital signatures
- Certificate fingerprints
- HMAC authentication
- Git commit hashing
Java Implementation:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;
public class SecureHashing {
public static byte[] sha256(byte[] data) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return digest.digest(data);
}
public static String sha256Hex(byte[] data) throws NoSuchAlgorithmException {
byte[] hash = sha256(data);
return DatatypeConverter.printHexBinary(hash).toLowerCase();
}
public static byte[] sha512(byte[] data) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
return digest.digest(data);
}
}
❌ PROHIBITED: MD5, SHA-1
Deprecated_Algorithms:
MD5:
Reason: Collision attacks practical since 2004
Replacement: SHA-256
Deadline: Immediate removal required
Exception: Git commit hashes (backward compatibility)
SHA-1:
Reason: Collision attacks demonstrated (SHAttered)
Replacement: SHA-256
Deadline: Immediate removal required
Exception: Git commit hashes (Git working on SHA-256 migration)
Password Hashing
✅ APPROVED: bcrypt, Argon2, PBKDF2
Algorithms:
bcrypt:
Cost_Factor: 12-15 (balance security and performance)
Use: Password storage, user authentication
Status: Preferred
Argon2id:
Memory: 64 MB
Iterations: 3
Parallelism: 4
Use: High-security password storage
Status: Preferred (if available)
PBKDF2-SHA256:
Iterations: 600,000+ (OWASP 2023 recommendation)
Salt: 128 bits minimum
Use: Password storage (fallback if bcrypt unavailable)
Status: Acceptable
Key_Principles:
- Always use unique random salt per password
- Store salt alongside hash
- Never use fast hashes (MD5, SHA-256) for passwords
- Cost factor should take ~100ms on production hardware
Java Implementation (bcrypt):
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class PasswordSecurity {
private static final int COST_FACTOR = 12;
private static final BCryptPasswordEncoder encoder =
new BCryptPasswordEncoder(COST_FACTOR);
public static String hashPassword(String plainPassword) {
return encoder.encode(plainPassword);
}
public static boolean verifyPassword(String plainPassword, String hashedPassword) {
return encoder.matches(plainPassword, hashedPassword);
}
}
Spring Security Configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
}
Encryption at Rest
Database Encryption (PostgreSQL)
RDS Encryption Configuration:
RDS_Encryption:
Encryption_at_Rest:
- Enable: AWS KMS encryption for RDS instance
- Key: Customer Managed Key (CMK) for high-classification data
- Key: AWS Managed Key for standard data
- Automated_Backups: Encrypted with same key
- Read_Replicas: Must use same encryption key
Connection_Encryption:
- SSL/TLS: Required for all connections
- Protocol: TLS 1.2 minimum, TLS 1.3 preferred
- Certificate_Validation: Verify server certificate
Column_Level_Encryption:
- Use: pgcrypto extension for sensitive columns
- Algorithm: AES-256-GCM
- Key_Management: Application-managed keys in AWS Secrets Manager
PostgreSQL SSL Configuration:
# application.yml - Spring Boot PostgreSQL SSL
spring:
datasource:
url: jdbc:postgresql://cia-db.cluster-xxx.eu-north-1.rds.amazonaws.com:5432/cia_db?ssl=true&sslmode=verify-full&sslrootcert=/path/to/rds-ca-cert.pem
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
hikari:
connection-timeout: 30000
maximum-pool-size: 10
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQL10Dialect
Column-Level Encryption (pgcrypto):
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE politician_sensitive (
id SERIAL PRIMARY KEY,
politician_id INTEGER NOT NULL,
ssn_encrypted BYTEA NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO politician_sensitive (politician_id, ssn_encrypted)
VALUES (
123,
pgp_sym_encrypt('197001011234', 'encryption-key-from-secrets-manager')
);
SELECT
politician_id,
pgp_sym_decrypt(ssn_encrypted, 'encryption-key-from-secrets-manager') AS ssn
FROM politician_sensitive
WHERE politician_id = 123;
S3 Bucket Encryption
S3 Encryption Configuration:
S3_Encryption:
Server_Side_Encryption:
SSE-S3:
Description: AWS managed encryption keys
Use_Case: Standard classification data
Key_Management: Fully managed by AWS
SSE-KMS:
Description: AWS KMS managed keys
Use_Case: High/Extreme classification data
Key_Management: Customer managed CMK
Audit: CloudTrail logs all key usage
SSE-C:
Description: Customer provided keys
Use_Case: Special compliance requirements
Key_Management: Customer manages keys entirely
Caution: Key loss = permanent data loss
Client_Side_Encryption:
Use: Extra layer for extreme classification
Implementation: Encrypt before upload to S3
Key_Storage: AWS KMS or client-side HSM
S3 Bucket Policy (Enforce Encryption):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnencryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::cia-data-bucket/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "aws:kms"
}
}
},
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::cia-data-bucket",
"arn:aws:s3:::cia-data-bucket/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
Java S3 Client Configuration:
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
public class S3EncryptionConfig {
public static void uploadEncrypted(S3Client s3Client, String bucket,
String key, byte[] data, String kmsKeyId) {
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.serverSideEncryption(ServerSideEncryption.AWS_KMS)
.ssekmsKeyId(kmsKeyId)
.build();
s3Client.putObject(request, RequestBody.fromBytes(data));
}
}
EBS Volume Encryption
EBS Encryption Best Practices:
EBS_Encryption:
Default_Encryption:
- Enable: Account-level default encryption
- Key: Customer managed CMK for production
- Snapshots: Automatically encrypted with same key
Encryption_by_Type:
Production_Volumes:
Key: Customer managed CMK
Rotation: Annual automatic rotation
Access: Restricted to EC2 instance role
Development_Volumes:
Key: AWS managed key acceptable
Rotation: Automatic by AWS
Access: Developer IAM roles
Migration:
Unencrypted_to_Encrypted:
- Create snapshot of unencrypted volume
- Copy snapshot with encryption enabled
- Create new encrypted volume from snapshot
- Attach to instance and update /etc/fstab
Enable Default EBS Encryption:
aws ec2 enable-ebs-encryption-by-default --region eu-north-1
aws ec2 get-ebs-encryption-by-default --region eu-north-1
aws ec2 modify-ebs-default-kms-key-id \
--kms-key-id arn:aws:kms:eu-north-1:123456789012:key/abc-123-def \
--region eu-north-1
Encryption in Transit
TLS/SSL Configuration
TLS Version and Cipher Suites:
TLS_Configuration:
Protocols:
Enabled:
- TLS 1.3 (Preferred)
- TLS 1.2 (Minimum)
Disabled:
- TLS 1.1 (Deprecated)
- TLS 1.0 (Deprecated)
- SSL 3.0 (Insecure)
- SSL 2.0 (Insecure)
Cipher_Suites_TLS_1_3:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
Cipher_Suites_TLS_1_2:
Preferred:
- ECDHE-RSA-AES256-GCM-SHA384
- ECDHE-RSA-AES128-GCM-SHA256
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-ECDSA-AES128-GCM-SHA256
Acceptable:
- AES256-GCM-SHA384
- AES128-GCM-SHA256
PROHIBITED:
- RC4 ciphers (all)
- DES/3DES ciphers
- Export ciphers
- NULL ciphers
- Anonymous ciphers (ADH, AECDH)
Features:
- Forward_Secrecy: Required (ECDHE/DHE)
- AEAD_Ciphers: Preferred (GCM, ChaCha20-Poly1305)
- Certificate_Validation: Required
- HSTS: Enabled (max-age=31536000)
- OCSP_Stapling: Enabled
NGINX TLS Configuration:
# /etc/nginx/conf.d/ssl.conf
# Strong TLS configuration for CIA platform
server {
listen 443 ssl http2;
server_name www.hack23.com;
# TLS certificates
ssl_certificate /etc/letsencrypt/live/hack23.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hack23.com/privkey.pem;
# TLS protocols
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
# TLS 1.3 cipher suites (automatic, cannot configure)
# TLS 1.2 cipher suites
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256';
# Diffie-Hellman parameters for forward secrecy
ssl_dhparam /etc/nginx/dhparam.pem;
# SSL session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/hack23.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
# Application configuration
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name www.hack23.com;
return 301 https://$server_name$request_uri;
}
Generate Strong DH Parameters:
openssl dhparam -out /etc/nginx/dhparam.pem 4096
Spring Boot TLS Configuration
application.yml TLS Settings:
server:
port: 8443
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: ${KEYSTORE_PASSWORD}
key-store-type: PKCS12
key-alias: cia-app
enabled-protocols: TLSv1.3,TLSv1.2
ciphers: >-
TLS_AES_256_GCM_SHA384,
TLS_AES_128_GCM_SHA256,
ECDHE-RSA-AES256-GCM-SHA384,
ECDHE-RSA-AES128-GCM-SHA256
client-auth: none
spring:
security:
headers:
hsts:
include-subdomains: true
max-age: 31536000
content-type:
enabled: true
frame:
deny: true
Java TLS Configuration:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
@Configuration
public class TLSConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainer() {
return factory -> factory.addConnectorCustomizers(connector -> {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
protocol.setScheme("https");
protocol.setSecure(true);
protocol.setSslEnabledProtocols("TLSv1.3,TLSv1.2");
protocol.setCiphers(
"TLS_AES_256_GCM_SHA384," +
"TLS_AES_128_GCM_SHA256," +
"ECDHE-RSA-AES256-GCM-SHA384," +
"ECDHE-RSA-AES128-GCM-SHA256"
);
protocol.setUseServerCipherSuitesOrder(true);
});
}
}
Key Management
AWS KMS Best Practices
KMS Key Architecture:
KMS_Key_Strategy:
Production_Data:
Type: Customer Managed CMK
Rotation: Automatic annual rotation enabled
Alias: alias/cia-production-data
Policy: Least privilege (specific IAM roles only)
Multi_Region: Consider for DR requirements
Development_Data:
Type: AWS Managed Key
Rotation: Automatic (managed by AWS)
Alias: aws/s3 (service default)
Policy: Broader access for development team
Backup_Encryption:
Type: Customer Managed CMK
Rotation: Annual
Alias: alias/cia-backups
Policy: Backup service + restore roles only
Create Customer Managed CMK:
aws kms create-key \
--description "CIA Production Data Encryption Key" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS \
--multi-region false \
--tags TagKey=Environment,TagValue=Production \
TagKey=Application,TagValue=CIA
aws kms create-alias \
--alias-name alias/cia-production-data \
--target-key-id <key-id-from-create>
aws kms enable-key-rotation \
--key-id <key-id>
aws kms get-key-rotation-status \
--key-id <key-id>
KMS Key Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow CIA Application to Use Key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/cia-application-role"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:GenerateDataKey"
],
"Resource": "*"
},
{
"Sid": "Allow CloudWatch Logs to Use Key",
"Effect": "Allow",
"Principal": {
"Service": "logs.eu-north-1.amazonaws.com"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:CreateGrant",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"ArnLike": {
"kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:eu-north-1:123456789012:log-group:*"
}
}
}
]
}
Key Rotation
Key Rotation Schedule:
Key_Rotation_Policy:
Symmetric_Keys:
KMS_CMK:
Frequency: Annual (automatic)
Method: AWS KMS automatic rotation
Backward_Compatibility: Old keys retained for decryption
Application_Keys:
Frequency: Quarterly
Method: Manual rotation with version tracking
Transition: Dual-key period (30 days)
Asymmetric_Keys:
TLS_Certificates:
Frequency: 90 days (Let's Encrypt)
Method: Automated renewal (Certbot)
Alert: 7 days before expiry
SSH_Keys:
Frequency: Annual
Method: Manual rotation per user
Validation: Remove old keys from authorized_keys
API_Keys:
Frequency: Quarterly or on compromise
Method: Generate new, deprecate old
Transition: 30-day overlap period
Automated KMS Key Rotation Verification:
#!/bin/bash
REGION="eu-north-1"
KEYS=$(aws kms list-keys --region $REGION --query 'Keys[].KeyId' --output text)
echo "Checking KMS Key Rotation Status..."
echo "======================================"
for KEY_ID in $KEYS; do
ALIAS=$(aws kms list-aliases --key-id $KEY_ID --region $REGION \
--query 'Aliases[0].AliasName' --output text 2>/dev/null)
ROTATION=$(aws kms get-key-rotation-status --key-id $KEY_ID \
--region $REGION --query 'KeyRotationEnabled' \
--output text 2>/dev/null)
if [ "$ROTATION" = "True" ]; then
echo "✅ $KEY_ID ($ALIAS): Rotation ENABLED"
elif [ "$ROTATION" = "False" ]; then
echo "⚠️ $KEY_ID ($ALIAS): Rotation DISABLED"
else
echo "ℹ️ $KEY_ID ($ALIAS): Not eligible for rotation (asymmetric key)"
fi
done
AWS Secrets Manager
Store Secrets Securely:
aws secretsmanager create-secret \
--name cia/production/db-password \
--description "PostgreSQL database password for CIA production" \
--secret-string "$(openssl rand -base64 32)" \
--kms-key-id alias/cia-production-data \
--tags Key=Environment,Value=Production \
Key=Application,Value=CIA
aws secretsmanager get-secret-value \
--secret-id cia/production/db-password \
--query 'SecretString' \
--output text
aws secretsmanager rotate-secret \
--secret-id cia/production/db-password \
--rotation-lambda-arn arn:aws:lambda:eu-north-1:123456789012:function:SecretsManagerRDSPostgreSQLRotationSingleUser \
--rotation-rules AutomaticallyAfterDays=30
Java Secrets Manager Integration:
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
public class SecretsService {
private final SecretsManagerClient client;
public SecretsService(SecretsManagerClient client) {
this.client = client;
}
public String getSecret(String secretName) {
GetSecretValueRequest request = GetSecretValueRequest.builder()
.secretId(secretName)
.build();
GetSecretValueResponse response = client.getSecretValue(request);
return response.secretString();
}
}
Spring Boot Secrets Manager Configuration:
spring:
datasource:
url: jdbc:postgresql://cia-db.cluster-xxx.eu-north-1.rds.amazonaws.com:5432/cia_db
username: ${sm://cia/production/db-username}
password: ${sm://cia/production/db-password}
cloud:
aws:
secretsmanager:
enabled: true
region: eu-north-1
Certificate Management
Let's Encrypt Automation
Certbot Installation and Configuration:
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
sudo certbot --nginx -d www.hack23.com -d hack23.com \
--email security@hack23.com \
--agree-tos \
--no-eff-email \
--redirect
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
Certificate Renewal Monitoring:
#!/bin/bash
DOMAIN="www.hack23.com"
ALERT_DAYS=7
EXPIRY=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | \
openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
echo "Certificate for $DOMAIN expires in $DAYS_LEFT days"
if [ $DAYS_LEFT -lt $ALERT_DAYS ]; then
echo "⚠️ WARNING: Certificate expires soon!"
exit 1
else
echo "✅ Certificate is valid"
exit 0
fi
AWS Certificate Manager (ACM)
Request ACM Certificate:
aws acm request-certificate \
--domain-name hack23.com \
--subject-alternative-names www.hack23.com \
--validation-method DNS \
--region eu-north-1
aws acm describe-certificate \
--certificate-arn arn:aws:acm:eu-north-1:123456789012:certificate/abc123
aws acm list-certificates \
--certificate-statuses ISSUED \
--region eu-north-1
Compliance Mapping
ISO 27001:2022
- A.8.24 - Use of Cryptography
- A.5.23 - Information Security for Cloud Services
- A.8.1 - User Endpoint Devices
NIST CSF 2.0
- PR.DS-1 - Data at rest is protected
- PR.DS-2 - Data in transit is protected
- PR.DS-6 - Integrity checking mechanisms verify software integrity
- PR.DS-8 - Integrity checking mechanisms verify hardware integrity
CIS Controls v8
- Control 3.11 - Encrypt Sensitive Data at Rest
- Control 3.10 - Encrypt Sensitive Data in Transit
- Control 14.4 - Enforce Remote Access Using Multi-Factor Authentication
- Control 14.8 - Encrypt Sensitive Information at Rest
NIST SP 800-175B
- Key Management: Guideline for Using Cryptographic Standards
- Algorithm Selection: Approved algorithms for federal use
- Key Establishment: Key agreement and transport
References
Examples from CIA Platform
Successful Implementation: Spring Security + bcrypt
The CIA platform uses Spring Security with bcrypt for password hashing:
@Entity
@Table(name = "application_user")
public class ApplicationUser {
@Column(name = "password_hash", nullable = false)
private String passwordHash;
}
@Service
public class AuthenticationService {
private final PasswordEncoder passwordEncoder;
public ApplicationUser registerUser(String username, String plainPassword) {
ApplicationUser user = new ApplicationUser();
user.setUsername(username);
user.setPasswordHash(passwordEncoder.encode(plainPassword));
return userRepository.save(user);
}
}
Successful Implementation: PostgreSQL SSL
CIA platform enforces SSL for all database connections:
# Production database connection with SSL
spring.datasource.url=jdbc:postgresql://cia-db.cluster-xxx.eu-north-1.rds.amazonaws.com:5432/cia_db?ssl=true&sslmode=require
Document Maintenance:
- Review Frequency: Annual
- Last Updated: 2024-01-15
- Next Review: 2025-01-15
- Owner: Security Team / CIA Project Maintainers