Lesson 1 of 1 in What Actually Stops Them
Three Defences, All Load-Bearing
A memory-hard hash, a rate limit that counts on both axes, and a comparison that does not leak. This platform runs all three, and this is why.
3 min read
Not yet reviewed
Three modules of attack, and the defences are few and specific. None of them is "make users choose better passwords" — you cannot, and the whole point of the attacks was that it does not matter. Every defence here is something the *defender* controls, and this platform implements all three.
One — a hash built to be slow
The hashcat module's entire lesson was that the algorithm decides everything. So the fix is the algorithm: a memory-hard function tuned to cost real time and memory per guess.
What an attacker wants you to use
A fast hash - MD5, SHA-256 - a hundred billion guesses a second.What this platform uses
argon2id, with tuned parameters. A few thousand guesses a second,
and a `needsRehash` check so the cost rises as hardware does.The needsRehash part matters over years rather than days: when the tuned parameters move — because GPUs got faster — a passphrase is transparently re-hashed at the new cost the next time its owner signs in. The floor keeps rising without anybody being locked out.
Two — rate limiting, on both axes
The hydra module ended by pointing at credential stuffing, and that is where rate limiting earns its place — but only if it counts the right things. This is the mistake almost everybody makes.
Limiting by username only
Five tries per account, then slow down.
-> An attacker sprays "Autumn2026!" at ten thousand
accounts, one try each, and never trips a thing.Limiting by username AND address
Five per account, AND a ceiling per source address.
-> The spray hits the address limit long before it
finds an account that reused that password.This is not a subtle refinement. A per-username limit does nothing against the most common real attack, because that attack makes one guess per account. The platform checks both axes at once, and the reason is written in the code beside the check.
Three — a comparison that does not leak
The smallest of the three, and the easiest to get wrong. Comparing a submitted token to the stored one with === returns the instant two bytes differ — and the time it took leaks how many leading bytes were right, which is enough to recover a secret one byte at a time.
token === expected leaks timing, one byte at a time
constant-time compare always takes the same time
- Line 2The platform compares secrets in constant time, always. It costs nothing, so there is no trade to weigh — and weighing it is the mistake, the same as it was in the secure-coding course.
What is deliberately not on this list
Password complexity rules. They are on almost every real list and they do more harm than good: they do not stop cracking — a rule mutates the predictable result — and they push people toward reuse and sticky notes. A length floor and a check against known-breached passwords does more than any symbol requirement ever has.
Your login limits attempts to five per username. Why does this barely slow credential stuffing?
Tip
If you audit one thing in an authentication system, check whether the rate limit counts by source address as well as by account. The username-only limit is the single most common way a real login is left open to the single most common real attack.