Hashing (SHA-2, SHA-3, BLAKE2/3). Digital signatures. TLS at the handshake level. Common crypto mistakes: nonce reuse, ECB mode, fast hashes for passwords. Lab 4: Hash-and-crypto-misuse exercise.
Reading (~30 min)
Read the Argon2 RFC summary (or the Wikipedia article on Argon2). Focus on the three parameters: memory cost, time cost, parallelism. Notice that these parameters make the hash slow in a controlled way, which is exactly what you want for password hashing. Compare to SHA-256: SHA-256 is designed to be fast (for bulk-hashing data integrity checks, not passwords) and has none of these tunable work factors.
Lecture outline (~1.5 hr)
Part 1: Hashing (30 min)
A cryptographic hash function takes arbitrary-length input and produces a fixed-length output (the hash or digest). The three properties:
- Pre-image resistance: Given the hash H(x), it is computationally infeasible to find x.
- Second pre-image resistance: Given x and H(x), it is computationally infeasible to find y != x such that H(y) = H(x).
- Collision resistance: It is computationally infeasible to find any pair (x, y) where x != y and H(x) = H(y).
The modern hash functions:
| Hash | Output size | Speed | Status |
|---|---|---|---|
| MD5 | 128 bit | Very fast | Broken (collisions found 2004); do not use for security |
| SHA-1 | 160 bit | Fast | Broken (SHAttered attack 2017); deprecated |
| SHA-256 (SHA-2 family) | 256 bit | Fast | Current standard for data integrity |
| SHA-512 (SHA-2 family) | 512 bit | Fast | Used where larger output is useful |
| SHA-3 (Keccak) | 224-512 bit | Moderate | NIST standard 2015; different internal design from SHA-2 |
| BLAKE2b / BLAKE3 | Variable | Very fast | Used in high-performance contexts (file checksums, git); BLAKE3 is the newest |
For data integrity (checksumming a file, verifying a download, signing a certificate): SHA-256 or SHA-3. BLAKE3 for performance-critical applications.
For passwords: never any of the above. See Part 3.
Part 2: Digital signatures (20 min)
A digital signature is an asymmetric operation: the signer uses their private key; anyone can verify using the signer's public key.
The signing process (conceptually):
- Compute the hash of the document:
h = SHA-256(document). - Sign the hash with the private key:
signature = Sign(private_key, h). - Publish the document and the signature together.
The verification process:
- Compute the hash of the received document:
h = SHA-256(received_document). - Verify the signature against the signer's known public key:
Verify(public_key, h, received_signature). - If the verification passes, the document came from the private-key holder and has not been modified.
Why hash before signing? Signing the full document directly is slow (asymmetric operations are expensive). Signing the hash is fast; the hash has fixed size regardless of document length.
Where you encounter digital signatures:
- TLS certificates (the CA signs the server's certificate)
- Software packages (apt, dnf, pip sign their packages)
- Git commits (gpg-signed commits use Ed25519 or RSA)
- JWT tokens (the backend signs the token; the frontend verifies it on each request)
Part 3: Password hashing and the case against fast hashes (20 min)
Password storage is not data integrity. The goal is not to verify that a file hasn't changed; the goal is to verify that a human knows a secret. These require different properties.
Why fast hashes fail for passwords:
A modern GPU can compute approximately 10 billion SHA-256 hashes per second. A leaked database of SHA-256-hashed passwords can be attacked with a dictionary + rules at 10 billion guesses per second. A six-character alphanumeric password has about 56 billion combinations. At 10 billion/sec, the entire space is searched in under 6 seconds.
The salt:
A salt is a random value appended to the password before hashing: H = SHA-256(password || salt). The salt is stored alongside the hash. Two users with the same password get different salts and therefore different hashes.
Salts defeat pre-computation attacks (rainbow tables, pre-built hash tables). But they don't slow down the GPU attack. The GPU computes SHA-256(guess || stored_salt) for every guess; the operation is still 10 billion/sec.
The slow KDF:
A key derivation function (KDF) designed for passwords adds a work factor that makes each guess take longer.
| KDF | Memory requirement | Tunable | Current recommendation |
|---|---|---|---|
| bcrypt | Fixed (4 KB) | Cost factor (rounds) | Acceptable; has 72-byte input limit |
| PBKDF2-HMAC-SHA-256 | Minimal | Iteration count | Acceptable; NIST-approved |
| scrypt | High, tunable | N, r, p | Good; memory-hard |
| argon2id | High, tunable | Memory, time, parallelism | Current recommendation (RFC 9106) |
A bcrypt hash with cost 12 takes approximately 250 ms on a modern server. The same attacker GPU doing 10 billion SHA-256/sec does roughly 4,000 bcrypt-cost-12 hashes/sec. Six-character alphanumeric space: 56 billion / 4,000 = 14 million seconds = about 160 days. Still feasible for a determined attacker, but a 12-character password is now practically infeasible.
The lesson for the hash cracking lab: the same password stored in MD5 and in bcrypt-cost-12 falls in under a second versus over a week. The difference is not the algorithm name; it is the work factor.
Part 4: TLS at the handshake level (20 min)
TLS 1.3 (current) is the version running on essentially all HTTPS connections today. The key exchange you learned in Week 4 is the core of the handshake.
Simplified TLS 1.3 handshake:
- ClientHello: The client sends its supported cipher suites and a public X25519 (or P-256) key-exchange value.
- ServerHello + Certificate + Finished: The server selects a cipher suite, sends its own key-exchange value, sends its certificate (signed by a CA), and sends a Finished message authenticated with the derived session key.
- Client Finished: The client verifies the certificate (is the CA trusted? does the certificate hostname match?), derives the same session key from the exchanged values, and sends its Finished message.
- Application data: Both sides send encrypted, authenticated application data using the derived symmetric keys.
The session keys are derived from the key-exchange values, not transmitted. An attacker who observes the handshake cannot derive the keys without the private key-exchange value (ephemeral key; discarded after the handshake). This is forward secrecy: even if the server's long-term private key is compromised later, past sessions cannot be decrypted.
What TLS does not hide:
- The server's IP address (visible to network observers)
- The SNI (Server Name Indication) in the ClientHello (the hostname the client is connecting to; an ESNI/ECH extension encrypts this but is not yet widely deployed)
- The certificate the server presents (the certificate chain is sent in the clear during the handshake)
- The timing and size of encrypted records
This is the same material covered in NET-101 Week 10. SEC-101 adds the "what can go wrong" layer: an attacker who controls a CA can issue a certificate for any domain; a misconfigured server that accepts weak cipher suites can be downgraded; a nonce-reusing TLS session leaks plaintext.
Lab exercises (~1.5 hr)
Lab 4: Hash-and-crypto-misuse exercise (graded)
See labs/lab-4-hash-cracking.md for the full lab.
The lab uses hashcat or John the Ripper to crack a small set of MD5-hashed and SHA-1-hashed passwords, then demonstrates that the same passwords salted and hashed with bcrypt resist the same attack.
Tier-1 companion (re-encounter from Week 4): Cipher Visualizer Workout
See worksheets/sec-101/lab-cipher-visualizer.md. Same worksheet introduced in Week 4; Tab 2 (Substitution / Caesar) and Tab 3 (Frequency Analysis) belong to this week. If you only did the Tab 1 XOR section in Week 4, finish Tabs 2 and 3 now.
- Tab 2: hand-shift
HELLO WORLDby 3 places; verify againstKHOOR ZRUOG - Tab 3: load the longer-passage example (shift 7; Declaration of Independence opening); identify the cipher-histogram peak; apply
shift = (cipher_peak - E + 26) mod 26; verify by dragging the shift slider - ~30 minutes for Tabs 2 + 3 if you finished Tab 1 in Week 4
Independent practice (~5 hr)
- Reading (1 hr): Read the "Password Storage Cheat Sheet" on the OWASP Cheat Sheet Series (owasp.org/cheatsheets/Password_Storage_Cheat_Sheet). This is the practical reference security engineers use to configure password storage correctly.
- picoCTF spine (3 hr): Focus on Cryptography challenges. Good targets: XOR cipher challenges, a simple RSA challenge (small key, no padding), or a challenge involving base-encoding or classical ciphers. If you're comfortable, try a challenge in the Forensics category that involves file format analysis.
- Reflection (1 hr): Write the prompts below.
Reflection prompts
-
A developer tells you: "We already hash passwords with SHA-256, and we add a random 8-byte salt before hashing. That's good enough." Explain in plain English what's right about their approach (they added a salt, which is better than nothing) and what's wrong about it (SHA-256 is still too fast for passwords). What would you recommend instead?
-
TLS provides forward secrecy because the session keys are derived from ephemeral key-exchange values that are discarded after the handshake. Explain why this matters for an attacker who records encrypted TLS traffic today and hopes to decrypt it in the future if they obtain the server's private key.
-
The OWASP Password Storage Cheat Sheet recommends a minimum work factor for bcrypt and argon2. Why does the recommended work factor increase over time? What drives the recommendation to revisit the work factor every couple of years?
Week 5 of 14. Next: Authentication and authorization (passwords, MFA, OAuth, JWTs).