Appendix G: Cryptography Reference

When attackers finally get into a network — and in the breaches that defined the last decade, they always eventually got in — the question that decides whether it is an embarrassing week or a company-ending year is rarely "did they get in?" It is "what did they find when they did?" A database of card numbers in plaintext is a hundred-million-dollar event; the same database as a correctly encrypted blob whose keys the attacker never reached is a non-event. That difference is decided by cryptography put in place long before the attacker arrived — and, far more often than by any broken algorithm, by whether that cryptography was chosen and configured correctly.

This appendix is the defender's quick-reference for those choices: which algorithms, which key sizes, which modes, and — the part that catches real bugs — which to refuse on sight. It is a companion to Chapters 4 (cryptography fundamentals), 5 (applied cryptography: TLS, VPNs, disk and database encryption), and 35 (the quantum threat and post-quantum cryptography). It is built to be reread before an exam or pinned next to a code review.

The governing principle, from Chapter 4: you are almost never going to break a cipher. Modern algorithms are, for practical purposes, unbreakable. Cryptography fails in the real world for completely different reasons — a key in a Git repo, a password "encrypted" with a scheme from 1995, a random number that was not random, a certificate nobody noticed had expired, a developer who rolled their own cipher. Your job is not to be a cryptographer; it is to use the cryptographers' work correctly. Everything in this appendix is a Tier 1, standard, verifiable fact, drawn from published standards (NIST FIPS and SP, RFC 8446, and the 2024 NIST post-quantum standards).


G.1 The four guarantees and which primitive provides them

Get the vocabulary exact, because the most expensive crypto mistakes come from confusing what a primitive provides. People say "we encrypted it" and believe they have solved a problem they have not touched.

Guarantee What it means Provided by NOT provided by
Confidentiality Keep data secret from those who should not read it Encryption (symmetric or asymmetric) Hashing; a plain MAC
Integrity Detect whether data has been altered Hash functions; MACs; authenticated encryption Encryption alone (a classic, dangerous assumption)
Authenticity Prove who created or sent something HMAC (shared secret); digital signatures (key pair) Encryption alone; a bare hash
Non-repudiation The signer cannot later credibly deny signing Digital signatures only HMAC (either party with the shared key could have made it)

The trap worth stating plainly because it has caused real breaches: encryption provides confidentiality, not integrity. Encrypt a message and an attacker who cannot read it can still flip ciphertext bits; you may decrypt to garbage — or, in some modes, to a different valid-looking message the attacker partially controls. The modern fix is authenticated encryption (AEAD), which does both in one operation precisely so engineers stop getting this wrong. And what cryptography does not do: it does not protect data in use (plaintext in memory while processed), it does not fix access control (the system happily decrypts for a compromised authorized account), and it does not make a system trustworthy end to end (a valid signature from a compromised build pipeline is a valid signature on malware).

🚪 Kerckhoffs's principle. A cryptosystem should remain secure even if everything about it except the key is public. The corollary is the most practical rule here: do not roll your own crypto, and do not trust secret algorithms. "Proprietary encryption" with a hidden algorithm is a red flag every time. The strong algorithms — AES, RSA, SHA-2 — are strong because they are public and have survived decades of scrutiny. What you keep secret is the key.


G.2 Symmetric encryption — algorithms, key sizes, and modes

Symmetric encryption uses one shared key for both encryption and decryption. It is extraordinarily fast — fast enough to encrypt every disk write, database field, and packet — and it does the bulk work in every real system. Its hard problem is key distribution (getting the shared key to both ends), solved by asymmetric crypto (§G.3).

Algorithm and key-size reference

Algorithm Status Key size(s) Block size Use
AES (Advanced Encryption Standard, FIPS 197) Current standard 128, 192, 256 bits 128-bit block The default for symmetric encryption — full stop
ChaCha20 (stream cipher, usually as ChaCha20-Poly1305) Current, widely used 256-bit key stream Excellent where hardware AES acceleration is absent (mobile, some embedded)
3DES (Triple DES) Deprecated 112/168-bit effective 64-bit block Legacy only; retiring (Sweet32 birthday attack on the 64-bit block)
DES (Data Encryption Standard) Broken 56-bit 64-bit block Never — brute-forceable in hours; cautionary tale only
RC4 (stream cipher) Broken variable stream Never — statistical biases make it readable

The defender's rule is short: AES, 128- or 256-bit. AES-128 and AES-256 are both secure for the foreseeable future; AES-256 is the common default for sensitive data and is what regulators and standards bodies expect to see. ChaCha20-Poly1305 is the right alternative where AES is not hardware-accelerated.

Modes of operation — where engineers actually go wrong

A block cipher only encrypts one fixed-size block. The mode defines how blocks chain together, and the wrong mode hands the attacker your plaintext through an unbroken cipher. This, not the algorithm, is what to scrutinize in a code review.

Mode Type Integrity? Verdict
GCM (Galois/Counter Mode) AEAD (authenticated) Yes (auth tag) Preferred. Confidentiality + integrity in one operation. The default choice.
CCM AEAD (authenticated) Yes Fine; common in constrained/wireless contexts.
ChaCha20-Poly1305 AEAD (authenticated) Yes Preferred alternative to AES-GCM where no AES hardware.
CTR (Counter) Stream-like, unauthenticated No Only with a separate MAC; nonce must never repeat under a key.
CBC (Cipher Block Chaining) Block, unauthenticated No Legacy; needs an unpredictable IV and a separate integrity check; padding-oracle history.
ECB (Electronic Codebook) Block, unauthenticated No Never. Identical plaintext → identical ciphertext; leaks patterns (the "ECB penguin"). A finding on sight.

Prefer authenticated encryption (AEAD): AES-GCM or ChaCha20-Poly1305. It produces an authentication tag the recipient verifies on decryption — if even one bit of ciphertext or associated data was altered, the tag fails and decryption is refused. That is the integrity property §G.1 said you needed.

IV / nonce rules — the least-known catastrophic mistake

An IV (initialization vector) or nonce ("number used once") makes encrypting the same plaintext twice yield different ciphertext. The rules:

  • It does not need to be secret, but it must be unpredictable (for CBC) or never reused with the same key (for CTR and GCM).
  • Nonce reuse under the same key in GCM is catastrophic — it can leak the relationship between plaintexts and even let an attacker forge messages. Unique nonce per encryption is not optional.
  • Generate IVs/nonces from a cryptographically secure random source, never a counter you might reset or a fixed "deterministic" value.

🛡️ Defender's Lens — what to check in a code review. Not "did they use AES?" (almost everyone does), but: Is it ECB? (instant finding). Is it an authenticated mode like GCM, or unauthenticated like CBC with no separate integrity check? Where does the IV/nonce come from — a CSPRNG, unique per key? Is one key used to encrypt an unbounded amount of data? The breach-grade bug lives in those answers, not in the cipher.


G.3 Asymmetric encryption — RSA, ECC, and equivalent strengths

Asymmetric (public-key) encryption uses a mathematically linked pair: a public key published to the world and a private key kept secret. Data encrypted with the public key can only be decrypted with the matching private key, which dissolves the key-distribution problem — there is no secret to distribute. It is slow and size-limited, so it is used to exchange a symmetric key, not to bulk-encrypt data (hybrid encryption: asymmetric to exchange an AES key, symmetric to do the work — the architecture under TLS).

Algorithm Hard problem Key-size guidance Notes
RSA Factoring the product of two large primes 2048-bit minimum; 3072 or 4096 for long-lived secrets. RSA-1024 is too weak to deploy. The classic; large keys; slow but ubiquitous.
ECC (elliptic-curve) Elliptic-curve discrete logarithm 256-bit (e.g., P-256) ≈ RSA-3072. P-384 for higher assurance. Much smaller keys, faster, dominant in mobile/IoT/modern TLS; more sensitive to implementation errors.
Diffie–Hellman (DH/ECDH) Discrete logarithm Use ephemeral ECDH (forward secrecy); finite-field DH groups ≥ 2048-bit Key exchange, not encryption; ephemeral form gives forward secrecy.

Equivalent-strength reference

The headline number every defender should remember: a 256-bit ECC key provides security roughly comparable to a 3072-bit RSA key. Approximate equivalences (per NIST guidance on comparable strengths):

Security level (bits) Symmetric RSA / finite-field DH ECC
112 3DES (legacy) RSA-2048 ~224-bit curve
128 AES-128 RSA-3072 256-bit (P-256)
192 AES-192 RSA-7680 384-bit (P-384)
256 AES-256 RSA-15360 512-bit (P-521)

128 bits of security is the modern floor. Note how RSA key sizes balloon for higher security while ECC scales gently — which is exactly why ECC dominates where size and speed matter. The trade-off: ECC is more sensitive to implementation mistakes (a bad random number during signing can leak the private key — see §G.7), so it must be done with vetted libraries, never by hand.


G.4 Hash functions — algorithms and uses

A hash function takes input of any size and produces a fixed-size digest, with three defining properties: deterministic (same input → same digest), one-way / preimage-resistant (cannot run backward), and collision-resistant (cannot feasibly find two inputs with the same digest). A hash uses no key — which is why it provides integrity (anyone can recompute and verify) but not confidentiality (it is not encryption; there is nothing to "decrypt").

Algorithm Status Digest size(s) Use
SHA-256 / SHA-512 (SHA-2 family, FIPS 180-4) Current standard 256 / 384 / 512 bits Integrity, digital signatures, certificates, HMAC, general use
SHA-3 (Keccak, FIPS 202) Current alternative 224–512 bits; SHAKE (XOF) variants A structurally different alternative to SHA-2; equally fine, less common in the field
BLAKE2 / BLAKE3 Current (non-NIST) variable Fast modern hashes; common in tools and some protocols (BLAKE2s in WireGuard)
SHA-1 Broken for security 160 bits Never for signatures/integrity-against-attacker (collision demonstrated publicly in 2017)
MD5 Broken 128 bits Never for security (collisions producible in seconds); non-security checksums only

Use SHA-256 (or SHA-2/SHA-3 generally) for integrity and signatures. Do not use MD5 or SHA-1 where collision-resistance matters — both are broken, and seeing them used to verify integrity or signatures is a finding. (MD5 used as a non-security checksum against accidental corruption is defensible, but never trust it against a deliberate attacker.) A broken hash breaks signatures, because you sign a hash: a collision lets an attacker get you to sign a benign document whose hash matches a malicious one (the 2017 SHA-1 collision is why SHA-1 retired from signing).

Hash vs. encryption (a frequent exam and design confusion): a hash is one-way and keyless (integrity, fingerprints, password storage); encryption is reversible (confidentiality). You "verify" a hash by recomputing it, never by "decrypting" it. If someone speaks of "decrypting a hash," they mean cracking it by guessing inputs — which is why password hashing needs the extra defenses in §G.5.


G.5 Password hashing — bcrypt, scrypt, Argon2

Storing passwords is where the naive application of §G.4 is a disaster, so get it exactly right. Never store passwords in plaintext. Storing a plain hash (even SHA-256) is barely better against a real attacker, for two reasons: precomputation (a rainbow table of common-password hashes turns a stolen hash into an instant lookup) and speed (general-purpose hashes are designed to be fast — billions of guesses per second on a GPU).

The two defenses you must pair:

  1. Salt — a unique, random value per password, stored alongside the hash. It need not be secret; its uniqueness defeats precomputation entirely (a rainbow table would have to be rebuilt per salt) and makes two identical passwords hash differently.
  2. A deliberately slow, password-specific algorithm with a tunable work factor — so one hash takes a meaningful fraction of a second, invisible to a user logging in once but crippling to an attacker's billions-per-second.
Algorithm Status Key properties Notes
Argon2 (Argon2id) Current recommendation Slow and memory-hard; tunable time, memory, and parallelism The modern default; memory-hardness blunts the GPU/ASIC advantage
scrypt Recommended Slow and memory-hard Good choice; predates Argon2
bcrypt Acceptable / widely deployed Slow, tunable cost factor Solid and battle-tested; not memory-hard; common input-length caveats
PBKDF2 Acceptable where mandated Slow via many iterations Not memory-hard; use a high iteration count; common in FIPS-constrained settings
SHA-256 / MD5 (bare) Wrong for passwords Fast, no work factor A finding — fast hashing is the enemy for passwords

For new systems, prefer Argon2id; scrypt and bcrypt are acceptable; never a bare fast hash. The algorithm choice made years earlier sets the severity of a future breach: a dump of salted-Argon2 hashes at a high work factor keeps most strong passwords safe and buys you time; a dump of plaintext or unsalted MD5 means assume every password is recovered and force a global reset (and expect credential-stuffing against your other systems).

⚠️ Common Pitfall: "We hash our passwords, so we're fine." The phrase that matters is "salted, with a slow / memory-hard, password-specific algorithm (Argon2 / scrypt / bcrypt) at an appropriate work factor." If a system hashes with raw SHA-256 and no salt, write the finding.


G.6 TLS 1.3 and cipher suites

TLS 1.3 (RFC 8446, 2018) is the version to standardize on for data in transit. It is faster (one round trip to first application data) and dramatically safer than TLS 1.2, having removed an entire museum of broken options. It provides confidentiality (authenticated symmetric encryption after the handshake), integrity (tamper detection), and authentication (the server's X.509 certificate, signed by a trusted CA).

TLS 1.3 cipher suites

TLS 1.3 only permits AEAD ciphers and always uses an ephemeral, forward-secret key exchange — so the suite names only the AEAD cipher and the hash. You cannot accidentally configure a non-forward-secret or non-authenticated suite in TLS 1.3, because the protocol removed them.

TLS 1.3 cipher suite Bulk cipher Hash Notes
TLS_AES_128_GCM_SHA256 AES-128-GCM SHA-256 The mandatory-to-implement baseline; excellent
TLS_AES_256_GCM_SHA384 AES-256-GCM SHA-384 Higher margin; excellent
TLS_CHACHA20_POLY1305_SHA256 ChaCha20-Poly1305 SHA-256 Great on mobile / no AES hardware
TLS_AES_128_CCM_SHA256 AES-128-CCM SHA-256 Less common; constrained environments

Reading a TLS 1.2 suite (still seen in the wild)

A TLS 1.2 suite names four things, e.g. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: ECDHE (key exchange — ephemeral elliptic-curve Diffie–Hellman; the "E" gives forward secrecy), RSA (authentication — the certificate's signature type), AES_128_GCM (bulk AEAD cipher), SHA256 (handshake hash). That is a good suite. Most "cipher-suite hardening" work is really about TLS 1.2, where the bad options still exist and must be explicitly disabled.

Forward secrecy

Forward secrecy (PFS) means compromising a server's long-term private key in the future does not let an attacker decrypt past sessions they recorded. It comes from the ephemeral key exchange (the "E" in ECDHE/DHE): each session's key derives from fresh, throwaway DH keys, discarded after the handshake; the long-term certificate key only authenticates. This is the direct defense against harvest-now-decrypt-later — record traffic today, steal the key later, and still get nothing.

TLS configuration — do / don't

Do Don't
Offer only TLS 1.2 and 1.3 Offer SSLv2/SSLv3/TLS 1.0/TLS 1.1 (all obsolete)
Require ephemeral key exchange (ECDHE/DHE) — forward secrecy Allow static-RSA key exchange (TLS_RSA_WITH_*) — no forward secrecy
Use AEAD ciphers (GCM, ChaCha20-Poly1305) Use RC4, 3DES, export-grade, or CBC-mode legacy suites
Order the server preference so the strongest suite wins Assume "supports strong ciphers" means "only strong ciphers"
Enforce HSTS; consider OCSP stapling Leave a weak suite enabled "for compatibility" without a plan

"We support strong ciphers" is not "we only support strong ciphers." A server offering AES-256-GCM and RC4 lets a downgrading attacker pick RC4. The bad option must be removed, not merely outvoted. Audit what your servers offer (with testssl.sh, sslscan, or nmap --script ssl-enum-ciphers against your own assets), not just what your modern browser happens to negotiate.


G.7 Crypto failures to avoid

Modern algorithms are unbreakable for all practical purposes, so essentially every real-world crypto failure is a failure of implementation, configuration, or operation. Internalize this catalog and you will catch the overwhelming majority of crypto problems you ever face — none of which require breaking any math.

# Failure What it looks like Fix
1 Rolling your own crypto Custom cipher, homemade key exchange, "XOR with a secret string" Use vetted libraries (cryptography, libsodium, platform crypto) and standard algorithms
2 Weak/deprecated algorithms MD5, SHA-1, DES/3DES, RC4, RSA-1024, ECB Recognize on sight; replace with AES-GCM, SHA-2/3, RSA-3072+/ECC-256+
3 Bad randomness Non-crypto PRNG (random()), seed from time, low boot entropy Always a CSPRNG (secrets, /dev/urandom, platform CSPRNG)
4 Nonce/IV reuse Fixed or repeating IV under one key (catastrophic in GCM) Unique nonce per encryption from a CSPRNG
5 Key-management failure Key in source/config/Git; key next to the data; never rotated; everyone can read it Separate key from data; KMS/HSM; least privilege; rotation; no keys in code
6 Encryption without integrity CBC alone, no separate MAC; malleable ciphertext Use AEAD (AES-GCM / ChaCha20-Poly1305)
7 Over-trusting a valid signature "Signed = safe," even from a compromised signer/pipeline Verification is necessary, not sufficient; protect signing keys; watch behavior

Category 5 — key management — is where defenders actually lose. It is operational, not mathematical: the strongest AES-256 is worthless if the key is hard-coded, stored beside the data, never rotated, or broadly accessible. Cryptography moves the problem from "protect the data" to "protect the key"; if you do not then protect the key, you have moved the problem, not solved it. For the highest-value keys, this reaches its hardware conclusion in an HSM (Hardware Security Module) — a tamper-resistant device that performs signing/decryption internally and never exports the private key in plaintext.

🛡️ Defender's Lens: Almost none of these are "the crypto was broken." They are "the crypto was used wrong." That is good news: your highest-leverage crypto work is not advanced mathematics — it is code review and configuration audit. Grep for MD5, DES, ECB, and random() in a crypto context; hunt for hard-coded keys; confirm authenticated modes; confirm a CSPRNG; confirm salts and slow password hashing; confirm certificates are inventoried and not expiring. Every one of those is a defensive skill you already have, pointed at the right target.


G.8 Post-quantum cryptography (PQC)

The quantum threat is unlike the others: a future event with a present deadline. A sufficiently large, error-corrected quantum computer running Shor's algorithm could efficiently solve the factoring and discrete-logarithm problems that RSA and ECC rely on — breaking the public-key cryptography behind nearly all key exchange, digital signatures, and authentication. Symmetric algorithms (AES) and hashes (SHA-2/3) are far less affected: a different quantum algorithm (Grover's) weakens them, but is countered by roughly doubling key sizes, so AES-256 remains strong. The crisis is specifically in public-key cryptography.

Why it matters today: harvest-now-decrypt-later. An adversary does not need a quantum computer today to attack your data with one tomorrow. They can capture and store your RSA/ECC-protected traffic now and decrypt the archive retroactively once a capable quantum computer exists. So the deadline is not "when will quantum break RSA?" but "how long must my data stay confidential, and could a quantum computer exist within that window?" For data that must stay secret for a decade or more — bank records, health data, long-lived signing keys — the clock is already running.

The NIST post-quantum standards (standardized 2024)

After a multi-year public competition, NIST standardized the first post-quantum algorithms in 2024 as Federal Information Processing Standards. These are real, current Tier-1 references a defender should know by name and number:

Standard Algorithm Derived from Purpose
FIPS 203 ML-KEM (Module-Lattice Key-Encapsulation Mechanism) CRYSTALS-Kyber Key establishment — agree a shared symmetric key, quantum-resistantly (the PQC replacement for RSA/ECDH key exchange)
FIPS 204 ML-DSA (Module-Lattice Digital Signature Algorithm) CRYSTALS-Dilithium Digital signatures — the primary general-purpose PQC signature scheme
FIPS 205 SLH-DSA (Stateless Hash-based Digital Signature Algorithm) SPHINCS+ Digital signatures — a hash-based alternative; conservative security assumptions, larger signatures

Year flag: the three standards above (FIPS 203, 204, 205) were finalized in 2024. If you cite the exact publication date or any later additions to the PQC suite (NIST has signaled further signature standards), confirm against the live NIST publication, as the post-quantum standard set continues to evolve.

Migration: crypto-inventory and crypto-agility

The hard part is not the algorithms; it is migration, because cryptography is embedded everywhere — TLS, code-signing, VPNs, stored data, tokens, firmware, vendor products you cannot inspect — and most organizations do not know where they use it. The first, indispensable step is a cryptographic inventory: what cryptography is used where, for what purpose, protecting what data, with what algorithm and key size. Then prioritize by quantum exposure = algorithm type × data confidentiality lifetime (asymmetric + long-lived data = highest; symmetric/hash = lowest). The enabling architecture is crypto-agility: designing systems so algorithms can be swapped by configuration, not by rebuilding — so this migration, and the next, become routine rather than crises.

Priority Profile Example
HIGH Asymmetric crypto and long-lived data (harvest-now-decrypt-later) A 10-year customer-data archive (RSA-wrapped AES); long-lived code-signing keys
MEDIUM Asymmetric crypto, short-lived data High-volume TLS sessions (ECDHE) — migrate the key exchange, but lower urgency
LOW Symmetric / hash only Password store (Argon2); AES-256 at-rest with a non-PQC-exposed key wrap

🔗 Connection: This section builds on Chapter 4 (symmetric vs. asymmetric, RSA/ECC, key sizes, hard problems) and is developed in Chapter 35 (threat evolution, the quantum clock, the crypto_inventory toolkit increment). The quantum threat is precisely a threat to the hard problems Chapter 4's asymmetric algorithms rely on — which is why this reference can keep the math light.


G.9 Quick-reference summary card

One screen to reread before an exam or audit.

Symmetric: AES-128/256 (default AES-256). Mode: AES-GCM (AEAD) or ChaCha20-Poly1305. Never ECB. Unique nonce per key, from a CSPRNG.

Asymmetric: RSA-3072+ (2048 minimum; never 1024) or ECC P-256+. 256-bit ECC ≈ 3072-bit RSA. Use ephemeral ECDH for forward secrecy. Hybrid encryption: asymmetric exchanges the key, symmetric does the work.

Hashing: SHA-256 (or SHA-2/SHA-3) for integrity and signatures. Never MD5 or SHA-1 for security.

Passwords: salted Argon2id (or scrypt/bcrypt) at an appropriate work factor. Never a bare fast hash.

TLS: TLS 1.2 and 1.3 only; AEAD suites only; ephemeral key exchange (forward secrecy); disable RC4, 3DES, export, static-RSA, CBC-legacy, MD5/SHA-1. TLS 1.3 = RFC 8446.

Post-quantum: FIPS 203 ML-KEM (key establishment), FIPS 204 ML-DSA (signatures), FIPS 205 SLH-DSA (hash-based signatures), standardized 2024. Symmetric/hash largely safe; public-key is the crisis. Start with a crypto-inventory; build crypto-agility; prioritize by harvest-now-decrypt-later exposure.

The do-not list (findings on sight): MD5, SHA-1, DES, 3DES, RC4, RSA-1024, ECB mode, static-RSA TLS suites, TLS 1.0/1.1/SSL, bare-fast-hash password storage, keys in source code, non-CSPRNG randomness, nonce reuse, encryption without integrity.

The one principle: crypto failures are almost never broken math. They are rolling your own, weak algorithms, bad randomness, nonce reuse, key-management lapses, encryption without integrity, and over-trusting a valid signature. Your leverage is code review and configuration audit, not cryptanalysis.

🔗 Connection: Appendix A (security frameworks) and Appendix E (compliance crosswalk) show where these cryptographic controls are required — PCI-DSS's "render stored cardholder data unreadable," GLBA's and HIPAA's encryption expectations, CSF's Data Security outcomes. This appendix is how to choose the algorithms that satisfy those requirements correctly. Chapters 4, 5, and 35 are the full treatment behind every table here.