Part 1: Foundations of Cryptography
Part 2: Classical Ciphers
Part 3: Mechanized Cryptography
Part 4: Theoretical Breakthroughs
Part 5: Modern Symmetric Cryptography
Part 6: Principles of Good Cryptosystems
Part 7: Introduction to Cryptanalysis
Why principles matter
Algorithms change. Principles do not. Use them to evaluate proposals, pick sane defaults, and explain why "it works on my machine" is not a security argument.
We will recap two foundations, spell out security properties and practical requirements, then close with a concise table you can use as a checklist.
Foundational ideas
Kerckhoffs's principle
Assume the adversary knows everything about your system except the key. Do not rely on the secrecy of code or configuration. Publish the algorithm; keep the key secret. That forces designs to survive scrutiny and limits the blast radius of leaks.
Shannon's confusion and diffusion
Confusion hides how key bits influence outputs. Diffusion spreads local changes across the whole block. Modern ciphers achieve both by repeating rounds: substitute (nonlinearity), mix/permute (spreading), and combine a round key each round. This approach is the backbone of DES (Feistel) and AES (SPN).
Security properties to aim for
The properties below define what "secure" should mean for a cipher and its mode; use them as a checklist when you choose, implement, or review a design.
Ciphertext should look random
To anyone without the key, ciphertext should be computationally indistinguishable from random bits. In practice, this means no visible patterns, no statistical biases, and nothing that compresses well. If identical plaintext blocks or fields produce repeated ciphertext patterns, the mode or implementation is wrong.
For example, if you encrypt the same credit card number twice and get identical ciphertext, your mode is broken.
No shortcuts to decryption without the key
Given only the ciphertext, there should be no shortcut to the plaintext. The best attack must be a brute force search over the key space, not finding algebraic relationships or patterns. SPNs use nonlinear substitution to break simple relations; Feistel networks make reversibility depend on knowing round keys, not on inverting the round function.
Adequate key space; no weak keys
Key space grows as a power of two: each added bit doubles the possibilities. A uniform 128-bit space has \(2^{128} \approx 3.4 \times 10^{38}\) keys. Even at \(10^{18}\) guesses/second, exhaustive search would take \(\sim 10^{20}\) seconds, far beyond the age of the universe. Size alone is not enough: designs must also avoid "weak keys" that create detectable structure.
This is why 56-bit keys (like DES), or even 64-bit keys are no longer secure — they can be broken in hours with modern hardware.
Resistance across attack models
Attackers rarely see only ciphertext. They may obtain encryptions of chosen plaintexts (CPA, chosen plaintext attack) or, in some settings, decryptions of chosen ciphertexts (CCA, chosen ciphertext attack, with limits). Aim for confidentiality that holds under CPA at a minimum, and prefer AEAD modes that remain secure when adversaries can submit chosen ciphertexts for decryption.
Robust against side-channel leaks
Side channels are accidental outputs: timing, cache activity, power draw, electromagnetic (EM) emissions, and faults.
Side channels matter most when attackers have physical access (smart cards, IoT devices) or share hardware (cloud computing). For typical web applications, focus first on algorithmic security.
Some examples of side-channel attacks include:
- Timing/cache: Table-based AES with secret-dependent lookups can leak keys via cache timing on shared hardware.
- Power/EM: Differential power analysis of smart cards recovers keys from current traces; EM probes do the same without physical contact.
- Faults: Glitching voltage/clock during public-key operations yields faulty outputs that reveal secrets; similar ideas apply to symmetric code paths.
Before we list defenses, keep one idea in mind: side channels succeed when observable behavior correlates with secrets. We defend against this by removing the correlation or by hiding it behind fresh randomness. The aim is to break the link between what the device does and what an attacker can measure.
Mitigations of these attacks include:
-
Constant-time code. Make control flow and memory access independent of secrets. No secret-dependent branches or array indices, so timing/cache behavior does not reveal keys.
-
Hardware instructions (AES-NI, ARM Crypto). Use fixed-latency CPU instructions that implement AES (and similar primitives) in silicon, avoiding table lookups and reducing timing/cache leakage.
-
Masking / blinding. Inject randomness so that what the attacker can measure no longer correlates with the true secret.
Masking (symmetric): XOR random masks into intermediate values and carry them through the round steps.
Blinding (public-key, sometimes symmetric): Randomize inputs/exponents, compute, then unblind. -
Avoid table lookups indexed by secrets. If an array index depends on a secret (for example,
T[state_byte]
), the CPU's cache can leak which entries you touched. Instead, compute the value with fixed arithmetic/logic that does not vary with the secret (for AES, you can implement the S-box with boolean operations rather than a table), or, if you must use a table, read a fixed set of entries every time and combine them with masks so the memory-access pattern is identical for all inputs.
Composability: stay secure in real systems
Composability means the cipher stays secure when you plug it into a real system with other pieces. Its guarantees should still hold when messages are split into chunks, resent, or sent by many devices sharing a key. A design that looks secure by itself can fail when these pieces interact.
Some patterns to remember:
- Confidentiality needs integrity. Encryption alone is malleable. AEAD binds a tag to the message so tampering can be detected and rejected.
- Per-message inputs are part of the contract. CBC needs a fresh, unpredictable IV (initialization vector) for the first block. CTR, GCM, and ChaCha20 require a per-message value (nonce—a "number used once"). These must be unique for a given key.
- Separate keys by purpose. Do not reuse one key for unrelated functions (encryption and message authentication). Keep interfaces narrow so components compose cleanly.
Practical requirements for cryptography
Efficiency
Throughput, latency, memory, and energy matter. AES is excellent with CPU support; ChaCha20 is fast and constant-time on general and embedded cores. Efficient designs make constant-time coding practical, which reduces timing leaks.
Minimal ciphertext expansion
Overhead should be small and predictable.
Encryption algorithms that would, for example, produce ciphertext that is twice as long as the plaintext would be ineffective: at the least, that would double storage space and cut the effective network bandwidth in half. Hence, we want ciphertext to be on the same order of magnitude as the plaintext.
Expect a bit of overhead, such as a per-message input (e.g., 96 bits in GCM) and an authentication tag (typically 128 bits). That keeps ciphertext close to plaintext size while enabling secure modes. Avoid custom paddings and variable, ad-hoc headers that complicate parsing and invite bugs.
Simplicity and universality
Fewer parameters and simple implementations mean fewer mistakes. Prefer widely implemented standards with clear defaults and mature libraries. Use high-level AEAD APIs instead of wiring encryption and authentication by hand.
Public algorithms, open analysis
Security through obscurity fails. Favor designs that have been public and pounded on for years. If a vendor offers "proprietary enhancements" but no security argument, walk away.
Keys: the real secret
Strong algorithms fail with weak keys or sloppy handling. Generate keys with the operating system's cryptographically secure generator; protect them in storage and use; rotate before per-key limits; and destroy them deliberately when retired.
A uniform 128-bit key already places exhaustive search far beyond plausible hardware. Keep that margin by managing keys carefully: never reuse per-message inputs with the same key, keep keys out of logs and crash dumps, and avoid sharing one key across unrelated functions.
Summary table
Principle | Why it matters | Rule of thumb | Common pitfalls | Example |
---|---|---|---|---|
Kerckhoffs | Survive disclosure; force scrutiny | Publish algorithms; keep only keys secret | "Proprietary crypto," hidden constants | WEP's RC4 key scheduling |
Confusion & diffusion | Destroy patterns and simple relations | Repeat substitution, mixing, and keying in rounds | Too few rounds; linear mixing only | Early stream ciphers |
Random-looking ciphertext | Hide structure and bias | No patterns, no compression, no repeats under proper mode use | ECB on data; repeating per-message inputs | Adobe's 2013 breach (ECB mode) |
No shortcuts w/o key | Make brute force the best generic attack | No algebraic shortcuts; sound S-boxes/rounds | Structural weaknesses; weak permutations | Linear cryptanalysis attacks |
Adequate key space, no weak keys | Push brute force beyond feasibility | ≥128-bit uniform keys; avoid special key classes | Short keys; keys with special structure | DES 56-bit keys |
Resistance across models | Match real attacker capabilities | Target CPA for secrecy; AEAD for CCA-style environments | "Ciphertext-only" mindset; omitting authentication | Padding oracle attacks |
Side-channel robustness | Prevent leaks via timing/cache/power/faults | Constant-time code; avoid secret-indexed tables; use HW instructions | Table lookups on secrets; data-dependent branches | AES cache timing attacks |
Composability | Stay secure when combined in protocols | AEAD by default; separate keys by purpose; obey per-message input rules | Padding-oracles; key reuse across functions | TLS protocol vulnerabilities |
Efficiency | Make secure choices usable | Match primitive to hardware (AES-NI vs. ChaCha20) | Choosing slow legacy ciphers (3DES) | Mobile battery drain |
Minimal expansion | Keep overhead practical | Small fixed per-message input + 128-bit tag typical | Ad-hoc padding; variable, fragile formats | Custom protocol bloat |
Simplicity & universality | Reduce configuration errors | Few modes, clear defaults, mature libraries | "Rolling your own" modes/APIs | Custom crypto implementations |
Public algorithms, open analysis | Benefit from open analysis | Prefer widely vetted standards | Vendor-secret tweaks and claims | Proprietary "enhancements" |
Keys: generation & handling | Security collapses if keys fail | OS CSPRNG, protect/rotate/destroy keys | Logs, dumps, reuse of per-message inputs | Hardcoded keys in code |
Conclusion
Symmetric cryptography matured from craft to engineering. Kerckhoffs taught us to trust keys, not obscurity. Shannon gave us a language to judge designs. The one-time pad proved perfect secrecy but not practicality. DES showed how to build round-based ciphers; AES showed how to deploy them at Internet scale.
Carry the principles, not just the names. Favor public designs, manage keys carefully, and use modes that match your problem. If the ciphertext looks like noise, the implementation is constant-time, and the parameters follow the rules, you are on solid ground.
As computing evolves—from quantum threats to new hardware—these principles will guide evaluation of tomorrow's algorithms just as they validate today's choices.
Key Takeaways for CS Students:
- Use AES-GCM or ChaCha20-Poly1305 for new projects
- Never implement crypto primitives yourself—use vetted libraries
- When in doubt, ask: "Would this survive if the source code leaked?"