Chapter 32: Applied Cryptography for Security Operations¶
Overview¶
Cryptography is the mathematical foundation of information security — protecting data confidentiality, ensuring integrity, authenticating identities, and enabling non-repudiation. Security operations professionals must understand not just how to use cryptography, but how it fails: weak algorithms, implementation errors, key management flaws, and quantum threats. This chapter covers symmetric and asymmetric cryptography, PKI, TLS, certificate management, cryptographic failures, and quantum-safe cryptography.
Learning Objectives¶
By the end of this chapter, students SHALL be able to:
- Describe the mathematics and appropriate use cases for symmetric and asymmetric encryption
- Implement proper key management and rotation procedures
- Analyze TLS/SSL configurations for vulnerabilities and misconfigurations
- Design and operate a Public Key Infrastructure (PKI)
- Identify cryptographic failures in systems and code
- Explain post-quantum cryptography (PQC) and migration planning
Prerequisites¶
- Basic mathematics (modular arithmetic helpful but not required)
- Understanding of SSL/TLS from a network perspective
- Chapter 30 (Application Security) — cryptographic failures in context
Why This Matters
In 2012, Flame malware used a novel MD5 chosen-prefix collision attack to forge a Microsoft code signing certificate — allowing it to install as a legitimate Windows update. In 2014, Heartbleed exploited a buffer over-read in OpenSSL to extract private keys from running servers. In 2017, ROBOT allowed passive RSA key decryption against HTTPS servers with PKCS#1 v1.5 vulnerabilities unchanged since 1998. Cryptography's failures are always catastrophic because attacks bypass all other security controls. A single cryptographic mistake can undermine years of security investment.
32.1 Symmetric Cryptography¶
32.1.1 Modern Symmetric Algorithms¶
| Algorithm | Key Size | Block Size | Security | Use Case |
|---|---|---|---|---|
| AES-128 | 128 bits | 128 bits | Secure | General purpose |
| AES-256 | 256 bits | 128 bits | Very secure | High-security, quantum-resistant margin |
| ChaCha20-Poly1305 | 256 bits | Stream | Secure | TLS, mobile (no AES-NI hardware) |
| 3DES | 112 effective bits | 64 bits | Deprecated | Legacy only — do not use |
| DES | 56 bits | 64 bits | BROKEN | Never use |
| RC4 | Variable | Stream | BROKEN | Never use |
32.1.2 Block Cipher Modes¶
| Mode | Properties | Use |
|---|---|---|
| ECB | No IV; identical blocks produce identical ciphertext | NEVER use |
| CBC | IV required; sequential; padding needed | TLS ≤1.2 (deprecated for TLS 1.3) |
| CTR | Stream mode; parallelizable; IV must be unique | Acceptable |
| GCM | Authenticated encryption; parallelizable; integrity check | Preferred for most use cases |
| CCM | Authenticated encryption; constrained environments | IoT |
# Python: AES-256-GCM (preferred authenticated encryption)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
# Key generation (do this ONCE and store securely)
key = AESGCM.generate_key(bit_length=256) # 32 bytes / 256 bits
aesgcm = AESGCM(key)
# Encrypt
nonce = os.urandom(12) # 96-bit nonce — MUST be unique per encryption!
plaintext = b"Sensitive data here"
additional_data = b"authenticated but not encrypted header"
ciphertext = aesgcm.encrypt(nonce, plaintext, additional_data)
# ciphertext includes 16-byte GCM authentication tag appended
# Decrypt (throws InvalidTag if ciphertext tampered)
decrypted = aesgcm.decrypt(nonce, ciphertext, additional_data)
# CRITICAL: Never reuse a nonce with the same key!
# GCM nonce reuse breaks confidentiality and integrity completely
# Use random nonce OR counter — never timestamp (not monotonic enough)
32.2 Asymmetric Cryptography¶
32.2.1 RSA¶
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# Key generation
private_key = rsa.generate_private_key(
public_exponent=65537, # Always 65537 (F4)
key_size=4096 # Minimum 2048; prefer 4096 for long-lived keys
)
public_key = private_key.public_key()
# Encryption (for small data, e.g., key wrapping)
ciphertext = public_key.encrypt(
plaintext,
padding.OAEP( # OAEP — always use this, not PKCS1v15
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Signing
signature = private_key.sign(
message,
padding.PSS( # PSS — always use this for signing
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
RSA Security Notes: - Minimum key size: 2048 bits (NIST deprecated 1024-bit in 2013) - PKCS#1 v1.5 padding → VULNERABLE to Bleichenbacher attack; use OAEP - RSA-1024 can be factored with sufficient compute; RSA-2048 is safe until ~2030 - Post-quantum threat: Shor's algorithm breaks RSA; see Section 32.6
32.2.2 Elliptic Curve Cryptography (ECC)¶
ECC provides equivalent security with much smaller keys:
| ECC Key Size | RSA Equivalent | Security Level |
|---|---|---|
| 256 bits (P-256) | 3072 bits RSA | 128-bit security |
| 384 bits (P-384) | 7680 bits RSA | 192-bit security |
| 521 bits (P-521) | 15360 bits RSA | 256-bit security |
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
# Ed25519 — modern, fast, safe (no weak curve parameters)
private_key = Ed25519PrivateKey.generate()
public_key = private_key.public_key()
signature = private_key.sign(message)
public_key.verify(signature, message) # Raises InvalidSignature if invalid
32.3 Hash Functions¶
| Algorithm | Output | Security | Use |
|---|---|---|---|
| SHA-256 | 256 bits | Secure | General hashing, HMAC |
| SHA-384 | 384 bits | Secure | TLS PRF, higher security |
| SHA-512 | 512 bits | Secure | High-security applications |
| SHA-3 (Keccak) | Variable | Secure | Alternative to SHA-2 |
| SHA-1 | 160 bits | DEPRECATED | Legacy only — SHAttered collision 2017 |
| MD5 | 128 bits | BROKEN | Never for security; only for checksums |
32.3.1 HMAC (Hash-based Message Authentication Code)¶
import hmac, hashlib
# HMAC — message authentication using shared secret
def sign_message(message: bytes, secret_key: bytes) -> bytes:
return hmac.new(secret_key, message, hashlib.sha256).digest()
def verify_message(message: bytes, signature: bytes, secret_key: bytes) -> bool:
expected = sign_message(message, secret_key)
# MUST use compare_digest — prevents timing attacks
return hmac.compare_digest(expected, signature)
32.3.2 Password Hashing¶
import bcrypt
import argon2 # argon2-cffi library
# bcrypt — battle-tested, salt included
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
# Work factor 12 = ~0.5 seconds per check (appropriate for 2026)
# Argon2id — recommended by OWASP (2024)
ph = argon2.PasswordHasher(
time_cost=2, # 2 iterations
memory_cost=65536, # 64 MB
parallelism=1, # 1 thread
hash_len=32,
salt_len=16
)
hash_str = ph.hash(password)
ph.verify(hash_str, password) # Raises VerifyMismatchError if wrong
32.4 Public Key Infrastructure (PKI)¶
32.4.1 PKI Architecture¶
graph TB
ROOT[Root CA\nOffline / HSM-protected\n20-year cert]
INTER[Intermediate CA\nOnline signing\n5-year cert]
LEAF1[TLS Certificate\nweb.example.com\n1-year cert]
LEAF2[Code Signing Cert\nSoftware Publisher\n2-year cert]
LEAF3[Client Auth Cert\nEmployee Identity]
ROOT -->|Signs| INTER
INTER -->|Signs| LEAF1
INTER -->|Signs| LEAF2
INTER -->|Signs| LEAF3
style ROOT fill:#e63946,color:#fff
style INTER fill:#1d3557,color:#fff 32.4.2 Certificate Lifecycle Management¶
# Let's Encrypt / ACME — automated certificate lifecycle
# Certbot — most common ACME client
# Initial certificate issuance
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d example.com -d "*.example.com" \
--preferred-challenges dns-01
# Auto-renewal (runs twice daily via cron)
echo "0 */12 * * * root certbot renew --quiet --deploy-hook 'systemctl reload nginx'" >> /etc/crontab
# Monitor certificate expiry across all domains
# cert-monitor.sh using openssl:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -dates \
| grep "notAfter"
# Bulk certificate monitoring (notify 30 days before expiry)
for domain in $(cat domains.txt); do
expiry=$(echo | openssl s_client -connect $domain:443 -servername $domain 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
days_left=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
if [ $days_left -lt 30 ]; then
echo "EXPIRING SOON: $domain — $days_left days ($expiry)"
fi
done
32.4.3 Certificate Transparency Monitoring¶
# Monitor CT logs for unauthorized certificates issued for your domain
# crt.sh API
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
python3 -c "
import sys, json, datetime
for cert in json.load(sys.stdin):
issuer = cert.get('issuer_name','')
domain = cert.get('name_value','')
date = cert.get('entry_timestamp','')[:10]
print(f'{date} | {domain} | {issuer}')
" | sort -r | head -20
# Automated monitoring: certspotter, facebook CT monitoring, Google CT monitor
32.5 TLS Security¶
32.5.1 TLS Configuration Hardening¶
# Nginx TLS 1.3 hardened configuration (2026)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# TLS 1.3 only (TLS 1.2 acceptable for compatibility)
ssl_protocols TLSv1.3 TLSv1.2;
# Strong cipher suites (TLS 1.3 handles its own; this is for TLS 1.2 compat)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off; # Let client choose in TLS 1.3
# DH parameters for key exchange
ssl_dhparam /etc/ssl/dhparam.pem; # openssl dhparam -out dhparam.pem 4096
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
# Session caching
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off; # Disable for perfect forward secrecy
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
}
# Generate DH params:
# openssl dhparam -out /etc/ssl/dhparam.pem 4096
32.5.2 TLS Vulnerability Reference¶
| Vulnerability | CVE | TLS Version | Mitigation |
|---|---|---|---|
| BEAST | CVE-2011-3389 | TLS 1.0 | Disable TLS 1.0/1.1 |
| POODLE | CVE-2014-3566 | SSL 3.0 | Disable SSL 3.0 |
| Heartbleed | CVE-2014-0160 | Any OpenSSL | Patch OpenSSL; revoke/reissue certs |
| FREAK | CVE-2015-0204 | TLS 1.x | Disable export cipher suites |
| LOGJAM | CVE-2015-4000 | TLS 1.x | Use DH params ≥2048 bits |
| DROWN | CVE-2016-0800 | SSLv2 | Disable SSLv2 entirely |
| ROBOT | CVE-2017-13099 | TLS 1.x | Disable RSA key exchange cipher suites |
| SLOTH | CVE-2015-7575 | TLS 1.x | Disable MD5 and SHA-1 in TLS |
32.5.3 SSL Labs Testing¶
# Automated TLS configuration testing
# sslyze — Python-based TLS scanner
pip3 install sslyze
python3 -m sslyze example.com:443 --json_out results.json
# testssl.sh — comprehensive TLS analysis
./testssl.sh --full https://example.com
# SSL Labs API (grade A+ target)
curl "https://api.ssllabs.com/api/v3/analyze?host=example.com&all=done" | \
python3 -c "import sys,json; d=json.load(sys.stdin); [print(e['ipAddress'], e['grade']) for e in d.get('endpoints',[])]"
32.6 Post-Quantum Cryptography¶
32.6.1 The Quantum Threat¶
| Algorithm | Classical Security | Post-Quantum Status |
|---|---|---|
| RSA-2048 | 112-bit equivalent | BROKEN by Shor's algorithm on CRQC |
| ECDH P-256 | 128-bit | BROKEN by Shor's algorithm on CRQC |
| AES-128 | 128-bit | Weakened to ~64-bit by Grover's (still okay) |
| AES-256 | 256-bit | Weakened to ~128-bit by Grover's (secure) |
| SHA-256 | 128-bit collision | Still secure |
| SHA-384/512 | 192/256-bit | Secure |
CRQC (Cryptographically Relevant Quantum Computer) — A fault-tolerant quantum computer with enough qubits to run Shor's algorithm against RSA-2048. Current estimates: 10-20 years away, but "harvest now, decrypt later" attacks are happening today.
32.6.2 NIST PQC Standards (2024)¶
NIST finalized the first post-quantum cryptographic standards in 2024:
| Standard | Algorithm | Use Case |
|---|---|---|
| FIPS 203 | ML-KEM (Kyber) | Key encapsulation / key exchange |
| FIPS 204 | ML-DSA (Dilithium) | Digital signatures |
| FIPS 205 | SLH-DSA (SPHINCS+) | Digital signatures (hash-based, conservative) |
| FIPS 206 | FN-DSA (FALCON) | Digital signatures (compact, efficient) |
32.6.3 PQC Migration Planning¶
CRYPTO-AGILITY MIGRATION ROADMAP:
Phase 1 (Now — 2026): Inventory
├── Identify all cryptographic usage across applications, infrastructure
├── Catalog: algorithm, key size, purpose, upgrade difficulty
├── Prioritize: data with long sensitivity lifetime first
└── Establish crypto governance policy
Phase 2 (2026-2028): Hybrid Mode
├── Implement hybrid schemes (classical + PQC in parallel)
├── TLS 1.3 + Kyber key exchange hybrid (already supported in Chrome/Firefox)
├── Begin code library upgrades to PQC-capable versions
└── Test interoperability
Phase 3 (2028-2030): Full Migration
├── Complete migration of high-value, long-lived data
├── PKI migration: issue PQC certificates
├── VPN/TLS: PQC-only or hybrid mode
└── Code signing: migrate to ML-DSA/FN-DSA
Phase 4 (2030+): Deprecation
├── Sunset RSA, ECDSA, ECDH in new deployments
└── Archive and protect long-lived keys until migrated
32.7 Key Management¶
32.7.1 Key Management Hierarchy¶
Key Hierarchy:
├── Master Key (KEK — Key Encryption Key)
│ ├── Stored in HSM or cloud KMS
│ ├── Never leaves secure boundary
│ └── Used to encrypt DEKs
├── Data Encryption Keys (DEK)
│ ├── Unique per data set/record
│ ├── Encrypted at rest by KEK
│ └── Rotated regularly
└── Ephemeral Session Keys
├── Generated per session
├── Never stored
└── Derived via ECDH / Kyber
32.7.2 HSM and Cloud KMS¶
# AWS KMS — managed key service
# Create Customer Master Key (CMK)
aws kms create-key --description "Production Database Encryption Key" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS # Managed by AWS
# or EXTERNAL for BYOK (Bring Your Own Key)
# Encrypt data with KMS
aws kms encrypt --key-id arn:aws:kms:us-east-1:123456789:key/KEY_ID \
--plaintext fileb://secret.txt --output text --query CiphertextBlob
# Automatic key rotation (yearly)
aws kms enable-key-rotation --key-id KEY_ID
# Azure Key Vault
az keyvault create --name MyVault --resource-group prod-rg --location eastus
az keyvault key create --vault-name MyVault --name MyKey --kty RSA --size 4096
az keyvault secret set --vault-name MyVault --name DatabasePassword --value "$(cat /dev/urandom | base64 | head -c 32)"
32.8 Benchmark Controls¶
| Control ID | Title | Requirement |
|---|---|---|
| Nexus SecOps-CRY-01 | Approved Algorithm Policy | No MD5, SHA-1, DES, 3DES, RC4, RSA-1024 in production |
| Nexus SecOps-CRY-02 | TLS Configuration | TLS 1.2+ minimum; A grade on SSL Labs; HSTS deployed |
| Nexus SecOps-CRY-03 | Certificate Management | Automated renewal; 30-day expiry alerting; CT monitoring |
| Nexus SecOps-CRY-04 | Key Management | All encryption keys in KMS or HSM; no keys in code or env vars |
| Nexus SecOps-CRY-05 | Password Hashing | bcrypt (rounds≥12) or Argon2id for all password storage |
| Nexus SecOps-CRY-06 | PQC Readiness | Crypto inventory complete; migration plan to NIST PQC standards documented |
Exam Prep & Certifications¶
Relevant Certifications
The topics in this chapter align with the following certifications:
Key Terms¶
Authenticated Encryption (AE/AEAD) — Encryption that simultaneously provides confidentiality and integrity/authenticity guarantees. AES-GCM and ChaCha20-Poly1305 are AEAD algorithms.
Certificate Transparency (CT) — A publicly auditable log of all TLS certificates issued by trusted CAs, enabling detection of mis-issuance.
HSM (Hardware Security Module) — A physical device providing tamper-resistant storage and processing for cryptographic keys and operations.
Perfect Forward Secrecy (PFS) — A property of key exchange protocols where compromise of long-term keys does not compromise past session keys.
Post-Quantum Cryptography (PQC) — Cryptographic algorithms believed to be resistant to attacks from both classical and quantum computers.
PKCS#1 v1.5 — An older RSA padding scheme vulnerable to the Bleichenbacher oracle attack. Always use OAEP for encryption and PSS for signatures.