Lion Cipher Lab
Migrate legacy password hashes to Argon2id without forcing a reset (wrap now, rehash on login)
- Identity & Access Management
- Intermediate
- ~75 min
- Free · no account required
Why it matters
Almost nobody gets to design password storage from scratch. You join a team, open the users table, and find 40-character hex strings: unsalted SHA-1, maybe a batch of salted MD5 from an acquisition years ago. The textbook fix is 'switch to Argon2id', but Argon2id needs the PASSWORD, and you only have the old hashes. Forcing 10,000 people to reset is a support disaster and looks like a breach. Waiting for each user to log in leaves every inactive account's weak hash sitting in the database for years. This lab teaches the move professionals use: wrap every legacy hash in Argon2id today, so the…
What you'll learn
- Designing a self-describing password-hash format with a scheme prefix so legacy and modern hashes can coexist during a migration
- Wrapping legacy SHA-1 and salted-MD5 digests in Argon2id on day zero, in one database transaction, without knowing any password
- Verifying a wrapped hash by recomputing the legacy digest of the presented password and checking it against the Argon2id wrapper
- Rehashing to plain Argon2id on successful login only, with a compare-and-swap update, and catching parameter upgrades with argon2-cffi's check_needs_rehash
- Measuring a rollout: accounts still wrapped after 30 days of realistic logins, by activity level
- Finding old hashes that survive an UPDATE in SQLite free pages, and removing them with VACUUM or secure_delete
- Explaining password shucking, where peppers belong, why bcrypt is an awkward wrapper, and when dormant accounts must be reset or disabled
Steps in this lab
- The problem you inherited, in plain words
- Three ways out, and why you pick the third
- Set up a workspace and install argon2-cffi
- Build the inherited database
- Make every stored hash say what it is
- Day zero: wrap every legacy hash in one transaction
- The old hashes were still in the file until VACUUM
- Replay 30 days of logins: rehash-on-login and a parameter raise
- Write the migration report and decide about dormant accounts
- A defender's benchmark: what each guess costs
- Honest negative: password shucking
- Pepper: optional, and only if you can keep it secret
- Why not wrap with bcrypt?
- Tuning parameters for production
- What you did, and the rollout checklist to keep