Argon2id vs PBKDF2:
Why I Upgraded LockedPages
PBKDF2 at 600,000 iterations takes about 150 ms on a modern CPU. On a consumer GPU with parallelism, it takes 2 ms — or less. That's a 75× attack advantage. Argon2id closes that gap by design. Here's the full story of why I made the switch and how.
The Problem With Iteration-Based KDFs
LockedPages uses a key derivation function (KDF) to turn a user's password into an AES-256 encryption key. For a long time, the industry standard for this was PBKDF2 — Password-Based Key Derivation Function 2. It's been in everything from iOS Keychain to Wi-Fi WPA2.
The idea is simple: apply a hash function repeatedly so that brute-forcing a password requires many computations instead of one. At 600,000 iterations using SHA-256, PBKDF2 is legitimately slow on a single CPU core: around 150 ms per guess.
The problem? Modern GPUs can run thousands of these computations in parallel. PBKDF2 was designed in 1999, when GPU cracking wasn't on the radar. It has no protection against parallel attacks because the algorithm has constant memory usage — each iteration uses the same tiny amount of RAM regardless of how many iterations you run.
A 2023 RTX 4090 can hash SHA-256 at over 22 GH/s. At 600,000 iterations, that's roughly 37,000 password guesses per second. An 8-character lowercase-plus-digit space is about 2.8 trillion combinations — roughly two and a half years to exhaust at that rate, or about fifteen months on average. Drop to seven characters and the same hardware is through the entire space in under a month.
PBKDF2: A Realistic Attack Scenario
Consider a user with the password summer2026 — 10 characters, lowercase + digits, common pattern. That's roughly 36^10 combinations, but password patterns dramatically reduce real-world entropy. Automated cracking tools with curated wordlists make this much faster than brute force.
With PBKDF2-SHA256 at 600,000 iterations, a modern GPU cracking rig can test tens of thousands of password guesses per second. A 10-character password using common patterns can fall in under a day; an 8-character dictionary word falls in minutes. The exact numbers depend on hardware, but the attack is well within practical reach on consumer equipment — let alone a rented cloud cluster.
The fundamental issue is that PBKDF2 is trivially parallelisable — each guess is completely independent and uses negligible memory.
PBKDF2 makes the attacker's problem cheap to parallelize. You can throw 1,000 GPU cores at it and get 1,000× the speed. Memory-hard functions break this relationship by requiring each guess to consume significant RAM — parallelism becomes the bottleneck.
How Argon2id Solves It
Argon2 won the Password Hashing Competition in 2015 and is OWASP's #1 recommendation for password hashing as of 2024. The "id" variant combines two approaches: Argon2i (resistant to side-channel attacks) and Argon2d (resistant to GPU/ASIC attacks).
The key insight is memory-hardness: Argon2id fills a large block of RAM with pseudorandom data and then processes it. To compute a single hash, you need to hold that entire memory block. This means:
- Running 1,000 parallel guesses requires 1,000× the RAM — not 1,000× the GPU cores
- Modern GPUs have limited per-core RAM (typically 1–4 KB), making mass parallelism impractical
- The cost of cracking scales with both time AND memory — a 2D cost function
Choosing the Right Parameters
Argon2id has three parameters: m (memory in KiB), t (time iterations), and p (parallelism). OWASP publishes minimum recommendations for interactive logins — enough to be genuinely expensive to attack at scale, while keeping the unlock experience fast enough on a mid-range phone.
The memory cost is the key. With 64 MB required per hash attempt, a GPU with 12 GB VRAM can run at most a few hundred parallel guesses. Compare to PBKDF2, which can run tens of thousands in parallel on the same hardware. The attacker's advantage evaporates. For LockedPages, I chose parameters at or above OWASP's interactive login recommendation — the unlock delay is noticeable but not frustrating, and that cost is the whole point.
Head-to-Head Comparison
| Property | PBKDF2-SHA256 (600K) | Argon2id (OWASP-recommended) |
|---|---|---|
| Memory per guess | ~1 KB | 64 MB |
| CPU time (modern device) | ~150 ms | ~400 ms |
| GPU parallelism | Thousands of cores | Limited by RAM |
| ASIC resistance | Low | High |
| OWASP 2024 recommendation | Fourth choice (not preferred) | Yes (#1 choice) |
| Android library availability | Built-in | argon2-android |
| Salt support | Yes | Yes |
| Estimated crack time (8-char weak) | Minutes to hours | Years on same hardware |
The Migration in LockedPages
Migrating a KDF in a zero-knowledge encryption app is non-trivial. The key is derived from the user's password — we don't store the key, only encrypted data. Changing the KDF means existing encrypted files need to be re-encrypted with a new key.
The migration strategy we used:
- Detect KDF version in file header. Each archive file carries a header field that records which KDF was used to derive the key. Old files are detected on open and flagged for upgrade.
- Prompt on first open after update. When the user opens an old file on the new version, they're prompted to "upgrade encryption." This requires their password once.
- Decrypt → re-encrypt in one pass. The app decrypts with the old PBKDF2-derived key, then re-encrypts with the new Argon2id-derived key. The plaintext never touches disk.
- Verify integrity before commit. Re-decrypt with the new key and confirm the result matches before overwriting the original. Never delete before verifying.
The original file is kept intact until the migration and verification both pass. On most Android devices the full migration per file is fast enough that users notice it only as a brief progress indicator — dominated by the Argon2id KDF call, which is intentionally slow.
Verdict
PBKDF2 isn't broken in the cryptographic sense — the SHA-256 hash underlying it is sound. But in 2026, for a privacy-first encryption app, using PBKDF2 when Argon2id is available is an unnecessary risk. The library support is there, the standards have caught up, and the user experience cost (slightly slower unlock) is justified by the security gain.
For LockedPages, the decision was clear: Argon2id with OWASP-recommended parameters. GPU-resistant, future-proof, and the standard will only strengthen over time as hardware improves.
If you're building a mobile encryption app and still using PBKDF2, this is your sign to upgrade.