◇ OpenCyber Academy
Professional · Chapter 10 · English

Chapter 10 — Cryptography and trust services: quality and troubleshooting

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 10 — Cryptography and trust services: quality and troubleshooting

Lesson map

Lesson 10 published. Map, example, EX046.

flowchart TD
  N0["Learning outcomes"]
  N1["10.1 A staff portal finding"]
  N2["10.2 Verifying the fix"]
  N3["Lab — Salted PBKDF2 versus fast hash"]
  N4["10.3 Quality through review"]
  N5["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5
  N5 --> EX["Worked example"]
  EX --> Q["Exercise EX046"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["10.1 A staff portal finding"]
  N2["10.2 Verifying the fix"]
  N3["Lab — Salted PBKDF2 versus fast hash"]
  N4["10.3 Quality through review"]
  N5["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX046"]
[Learning outcomes]
    |
    v
[10.1 A staff portal finding]
    |
    v
[10.2 Verifying the fix]
    |
    v
[Lab — Salted PBKDF2 versus fast hash]
    |
    v
[10.3 Quality through review]
    |
    v
[Synthesis]
    |
    v
[Worked example] --> [Exercise EX046]

Learning outcomes

You will (1) troubleshoot a password storage weakness in a staff portal; (2) verify a fix using a key-derivation function; (3) improve workflow quality with review and retrospectives.

10.1 A staff portal finding

Bayside's small staff rota portal, built by the agency, stores staff passwords. During a review Dana sees in the configuration export that passwords are stored as unsalted SHA-256 hashes. Fast hashes let an attacker who steals the database test enormous numbers of guesses quickly, and without salt, identical passwords produce identical hashes. Password storage needs a slow, salted function. Python's hashlib.pbkdf2_hmac implements PBKDF2, and stronger memory-hard choices include scrypt from RFC 7914 and Argon2id from RFC 9106. Dana's recommendation is to use a maintained library implementing one of these, not to design a custom scheme.

10.2 Verifying the fix

The agency proposes PBKDF2-HMAC-SHA-256 with a random 16-byte salt per user and a high iteration count set by policy, migrating each user at next login. Dana verifies the approach in a lab with synthetic users: two staff with the same password get different stored values; the correct password verifies and a wrong one fails; and the time per guess is far higher than for a single SHA-256. The lab below shows these results. She records that the lab confirms behaviour of the method, while the agency's production code still needs its own review.

Lab — Salted PBKDF2 versus fast hash

# Salted PBKDF2-HMAC-SHA-256 vs one SHA-256, synthetic staff. Teaching only; use a maintained library in production.
import hashlib, hmac, secrets, time
ITER = 600_000   # lab value; production iteration count comes from policy
def store(pw):
    s = secrets.token_bytes(16); return s, hashlib.pbkdf2_hmac("sha256", pw, s, ITER)
def check(pw, rec): return hmac.compare_digest(hashlib.pbkdf2_hmac("sha256", pw, rec[0], ITER), rec[1])
a, b = store(b"Rota-Clinic-3"), store(b"Rota-Clinic-3")
print("same password, different stored values:", a[1] != b[1])
print("correct password:", check(b"Rota-Clinic-3", a), "| wrong password:", check(b"Rota-Clinic-4", a))
t0 = time.perf_counter(); [hashlib.sha256(b"Rota-Clinic-3").digest() for _ in range(10000)]; fast = (time.perf_counter() - t0) / 10000
t0 = time.perf_counter(); check(b"x", a); slow = time.perf_counter() - t0
print(f"per-guess cost ratio PBKDF2/SHA-256: {'over 10,000x' if slow / fast > 10000 else 'under 10,000x'}")

Run with python3 lab_pbkdf2.py. Verified output:

same password, different stored values: True
correct password: True | wrong password: False
per-guess cost ratio PBKDF2/SHA-256: over 10,000x

10.3 Quality through review

Mistakes slip into every workflow, so Copperleaf builds quality checks in. Every report is reviewed by a second analyst before it goes to the client. After each monthly cycle, the team spends fifteen minutes on a retrospective: what went well, what went wrong and one change for next month. When Dana's retest of the chain fix nearly missed the second server, the retrospective led to a rule that load-balanced endpoints are tested once per backend. Small, steady improvements like this raise the quality of the whole service more than occasional heroic efforts.

Worked example

Dana documents the unsalted SHA-256 finding, runs the PBKDF2 lab to confirm the agency's approach and adds a per-backend testing rule after a retrospective.

Synthetic case. The rota portal, users and iteration count are synthetic; RFC 7914 and RFC 9106 are real.

Errors and limits

Lab timing varies by machine; it shows relative cost, not attacker speed. Upgrade at login leaves inactive accounts on old hashes.

Exercises

Synthesis

Quality comes from verifying fixes with sound methods and from steady review and retrospectives.

Continue studying — chapter 10 of 12

← Chapter 09 (draft) · Course chapter index · Chapter 11 (draft) →