Password Cracking and Wordlist Engineering Part 8: The Defensive Mirror — Passphrases, KDFs, and Why Rotation Policies Miss the Point

Seven parts of offense in this series, all in service of this one — the same structure Part 10 of the Impacket series closed with, and the same underlying point: understanding exactly how a crack happens is what makes the defensive advice specific instead of generic. “Use a strong password” is true and useless. What follows is neither.

The fast/slow divide, with Argon2 added

Part 2 put real numbers on the gap between fast and slow hashes. Filling in the rest of that table with more of the same RTX 4090 benchmark, plus one addition:

Hashhashcat modeRTX 4090 speedDesign goal
NTLM1000288.5 GH/sSpeed (1990, never meant for password storage)
Kerberoast / AS-REP13100 / 18200~3.5 GH/sSpeed (Kerberos protocol requirement, not a choice)
PBKDF2-HMAC-SHA256109008,865.7 kH/sTunable iteration count
sha512crypt18001,179.6 kH/sTunable rounds (Unix /etc/shadow default)
bcrypt, cost 53200184.0 kH/sTunable Blowfish key schedule cost
scrypt89007,126 H/sMemory-hard — needs RAM, not just cycles, per guess
Argon234000 (hashcat ≥ 7.0)Memory-hard, tunable memory and time and parallelism

Argon2 is a deliberate addition to this table rather than an afterthought: hashcat only gained Argon2 support (mode 34000) in version 7.0.0, released in 2025 — for years, one of the practical arguments for choosing Argon2 was that mainstream GPU cracking tooling simply didn’t support it yet. That’s now closed, which is itself the right lesson: “the popular cracker doesn’t support this KDF” is a temporary property of tooling, not a durable security property of the algorithm. Argon2’s actual resistance comes from memory-hardness — a GPU has thousands of small, fast compute cores but comparatively little memory per core, so a KDF that requires real RAM per guess in flight narrows the parallelism advantage a GPU has over a CPU far more than a purely compute-bound cost factor like bcrypt’s does.

What cost-factor tuning actually buys, in real numbers

bcrypt’s cost factor is a log2 round count, and Part 2’s 184.0 kH/s figure was measured at cost 5 — deliberately low, because that’s what a raw benchmark uses to get a clean throughput number. Move to cost 10, a realistic production setting, and each increment doubles the work per hash: five more increments is 2^5 = 32× more expensive, dropping throughput to roughly 5.75 kH/s on the same RTX 4090. Recomputing Part 2’s exhaustive 8-character brute-force table with that adjustment: 95^8 ÷ 5,750 ≈ 1.15 × 10^12 seconds — roughly 36,000 years, on hardware that clears the equivalent NTLM keyspace in an afternoon. That single tunable number — the cost factor a defender sets once, at rest, with no code change beyond a config value — is doing more real work than any password-composition rule in this entire series.

Complexity policies have less entropy than they advertise

Part 6 built hashcat’s bundled 8char-1l-1u-1d-1s-compliant.hcmask — 40,824 masks covering every positional arrangement of “one upper, one lower block, digits, one special” — and showed it searches roughly 65,000 times less keyspace than a genuinely arbitrary 8-character brute force. That number is the entire critique of composition-rule policies stated mathematically: a policy that mandates shape rather than length doesn’t just fail to guarantee strength, it hands an attacker a smaller, enumerable search space in exchange for the false confidence of “contains upper, lower, digit, symbol.” The password Sc4nn3r2019! this series spent Parts 5 and 7 cracking satisfies that exact policy and was still found in under a second of GPU time, because the policy shaped the search space without adding real entropy to it.

Length does what composition rules only pretend to. Each additional character in a genuinely unpredictable password multiplies the keyspace by the charset size; each additional composition rule just rearranges a fixed-length space into a smaller, more structured one. This is not a novel argument — it’s the actual, current position of the standards body that sets US federal password guidance.

What NIST actually says now

NIST SP 800-63B Revision 4, finalized in 2025, is explicit and — compared to the 2017 revision it replaced — considerably more direct: verifiers SHOULD NOT require passwords to be changed arbitrarily or on a fixed schedule, and SHALL force a change only on actual evidence of compromise. Composition rules (mandatory upper/lower/digit/symbol) are dropped entirely in favor of a length floor — a recommended 15 characters for password-only authentication, 8 as an absolute minimum when paired with MFA — plus mandatory screening against known-breached password lists.

That last point closes a loop this entire series opened with: the standard now explicitly recommends checking new passwords against exactly the kind of corpus Part 1 introduced — rockyou.txt and lists like it — not to crack anything, but to reject a password at creation time if it’s already sitting in a breach corpus an attacker will try in the first thirty seconds of any real attack.

Why forced rotation specifically backfires

The mechanism is the uncomfortable part, and it’s the same mechanism Part 5 spent an entire post building deliberately: forced periodic rotation, without a length or entropy floor to go with it, trains users toward predictable transforms of a password they already know, rather than toward genuinely new ones. Sc4nn3r2019! becoming Sc4nn3r2020! on next rotation isn’t a hypothetical — it’s precisely the shape best64.rule’s number-increment rules and this series’ own custom rule file are built to catch, because it’s precisely the shape human password rotation under a forced-change policy actually takes. A policy whose entire purpose is defeating an attacker who’s seen an old password ends up handing that same attacker a rule file for the new one.

What specifically would have stopped both cracks in this series

Six controls, each one closing a specific gap this series actually walked through — not generic advice, the exact fix for the exact mechanism:

svc-legacy-scan’s AS-REP hash never should have existed. Kerberos pre-authentication being disabled is what made GetNPUsers.py able to request a crackable ticket with zero credentials at all, back in Part 3 of the Impacket series. Enforcing pre-auth on every account closes this before password strength is even a relevant question.

svc-backup’s Kerberoast exposure is a gMSA problem, not a password problem. A Group Managed Service Account’s password is a 240-byte machine-generated secret rotated automatically — outside human choice entirely, meaning nothing in Parts 4 through 7 of this series (OSINT wordlists, custom rules, combinator attacks) has any vocabulary to work from. This is Part 4 of the Impacket series’ own recommendation, and it’s worth restating here because this series just demonstrated concretely what “worth migrating” actually means in cracked-in-under-a-second terms.

Length over composition, for the accounts that must stay human-chosen. A 15-character minimum with no shape requirement, per current NIST guidance, would have pushed both this series’ targets outside the reach of Part 6’s structured mask lists and made Part 5’s targeted rule-writing dramatically harder to aim.

Breach-corpus screening at password-set time, not just at crack time. Checking new passwords against rockyou-class lists — and organization-specific breach data where available — stops the weakest tier of password before it’s ever hashed and stored.

Slow, memory-hard KDFs for anything under human control. Part 2 and this post’s numbers say the rest: the same wordlist-and-rule pipeline that cracked two RC4-HMAC Kerberos hashes in seconds takes 36,000 years against bcrypt at a realistic cost factor, and Argon2’s memory-hardness pushes the GPU disadvantage further still.

No forced rotation without a compromise trigger. Current NIST guidance and this series’ own Part 5 rule-writing exercise agree on the mechanism, from opposite sides of the same problem: periodic mandatory rotation predictably produces exactly the transform pattern a rule-based cracking pass is built to catch.

None of these six are exotic. They’re also, notably, not “train users to pick better passwords” — every one of them is a system-level control that makes the system resilient regardless of what any individual person chooses, which is the actual, durable lesson eight parts of this series keep landing on from different directions: password security that depends on human behavior being consistently excellent is security that’s already lost the argument to a GPU that costs thirty cents an hour.