← Back to Blog

Argon2id: Why Memory-Hard Hashing Matters

Argon2id: Why Memory-Hard Hashing Matters - QNSQY post-quantum encryption guide

The Problem with Passwords (And Why Your "Clever" One Is Not Enough)

Here is an uncomfortable truth: most people's passwords are guessable. Not because people are stupid, but because humans are terrible at generating randomness. We pick words we can remember, we substitute letters with numbers in predictable ways ("a" becomes "@", "o" becomes "0"), and we reuse the same patterns across accounts.

Attackers know this. They do not sit at a keyboard typing guesses one by one. They use specialized software that can try millions, or even billions, of password combinations per second. They use:

  • Dictionary attacks: Trying every word in every language, plus common names, phrases, song lyrics, and movie quotes. These dictionaries are enormous, compiled from decades of data breaches.
  • Rule-based attacks: Taking dictionary words and applying common transformations. "password" becomes "P@ssw0rd!", "Password1!", "p@$$word", "password2024", and thousands of other variants. The most popular password-cracking tool, Hashcat, ships with rule files that generate hundreds of mutations for every base word.
  • Credential stuffing: Using passwords leaked from one breach against other services, because people reuse passwords.
  • Brute force: Trying every possible combination of characters for a given length. For short passwords, this is fast. For an 8-character password using lowercase letters, there are only about 209 billion possibilities, which a modern GPU can exhaust in minutes.

The question is not whether an attacker can guess your password. The question is how long it takes them. And the answer to that question depends almost entirely on the password hashing algorithm protecting it.

Why You Cannot Just Encrypt a Password

When you type a password to encrypt a file, the software needs to turn your password into an encryption key. An AES-256 key is exactly 256 bits (32 bytes) of what looks like random data. Your password is a string of characters that could be 8 characters or 40 characters, and it is definitely not random-looking.

A naive approach would be to just hash your password with a fast hash function like SHA-256. SHA-256 takes any input and produces a 256-bit output. Problem solved? Not even close.

SHA-256 is designed to be fast. On a modern CPU, SHA-256 can compute about 30 million hashes per second. On a high-end GPU (like those used for gaming or AI training), it can compute billions of hashes per second. If an attacker has your encrypted file and knows it was protected with a password hashed through plain SHA-256, they simply try passwords at billions per second until one produces a key that decrypts the file.

This is the fundamental problem. Fast hash functions are designed for integrity checking (verifying that a file has not changed), not for protecting passwords. For password protection, you want the opposite of fast. You want slow.

The History of Slow Hashing: From PBKDF2 to bcrypt to scrypt

Cryptographers recognized this problem decades ago and developed specialized "password hashing functions" designed to be deliberately slow.

PBKDF2 (Password-Based Key Derivation Function 2), published in 2000 as RFC 2898, was one of the first widely adopted solutions. It works by running SHA-256 (or another hash) thousands of times in a loop. If one SHA-256 hash takes a microsecond, running it 100,000 times takes a tenth of a second. This slows down attackers proportionally.

The problem with PBKDF2 is that it only requires CPU computation. GPUs have thousands of cores that can each run SHA-256 independently. An attacker with a rack of GPUs can simply run PBKDF2 in parallel across all those cores. The "slowness" of PBKDF2 can be overcome by throwing more hardware at the problem. A single high-end GPU can still compute millions of PBKDF2 hashes per second.

bcrypt, designed by Niels Provos and David Mazieres in 1999, improved on PBKDF2 by using a more complex internal structure that is harder to parallelize on GPUs. It is still widely used and is a solid choice for password hashing. But bcrypt has a fixed memory usage of 4 KB, which means it can still be implemented efficiently on specialized hardware (ASICs and FPGAs).

scrypt, designed by Colin Percival in 2009, introduced the concept of memory-hardness. Instead of just requiring CPU cycles, scrypt requires a large block of memory that must be accessed throughout the computation. This was a breakthrough: memory is expensive, and building custom chips with large amounts of fast memory is much harder than building chips with lots of CPU cores.

Each generation solved a real problem but left room for improvement. Argon2 was designed to be the definitive answer.

Argon2: Winner of the Password Hashing Competition

In 2013, a group of cryptographers organized the Password Hashing Competition (PHC), modeled after the competitions that produced AES and SHA-3. The goal was to find the best possible password hashing algorithm through open, public analysis.

Twenty-four candidates were submitted. After two years of review by the cryptographic community, the winner was announced in July 2015: Argon2, designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.

Argon2 was subsequently standardized as RFC 9106 by the IETF in 2021, and it is recommended by OWASP (the Open Worldwide Application Security Project) as the primary choice for password hashing.

How Argon2id Works: Memory as a Weapon

The core insight behind Argon2 is simple but powerful: make attackers need lots of memory.

A GPU might have 10,000 compute cores, but it typically has 24 GB of memory total. If each password attempt requires 128 MB of memory, the GPU can only run about 180 attempts in parallel, not 10,000. A CPU with 16 GB of RAM can only run about 125 attempts in parallel. The amount of memory, not the number of cores, becomes the bottleneck.

Here is what happens step by step when Argon2id processes your password:

  1. Allocation: Argon2id allocates a large block of memory (in QNSQY, 128 MB at minimum). This block is divided into a grid of 1 KB segments.
  2. Filling (data-independent phase): The first pass fills the memory block with data derived from your password, a random salt, and the configured parameters. The filling pattern is independent of the password value, which prevents timing side-channel attacks during this phase.
  3. Mixing (data-dependent phase): Subsequent passes read from pseudo-random locations in the memory block and use the values found there to update other locations. The access pattern depends on the data itself, making it harder for an attacker to predict which memory locations will be needed and precompute results.
  4. Finalization: After all passes are complete, the final state of the memory block is compressed down to the output key (typically 256 bits for an AES key). The output depends on the entire memory block. You cannot skip any part of it or compute the output from a subset of the data.
Why you cannot cheat on memory: An attacker might try to use less memory and recompute values on the fly instead of storing them. This is called a "time-memory tradeoff." Argon2's design makes this extremely expensive. Using half the memory roughly quadruples the computation time. Using a quarter of the memory makes it roughly 16 times slower. The mathematics of the memory access pattern ensure that any shortcut on memory is punished by a severe increase in computation.

The Three Argon2 Variants: d, i, and id

Argon2 comes in three variants, each designed for different threat models:

Argon2d (data-dependent): The memory access pattern depends on the password itself. This provides the strongest resistance against GPU and ASIC attacks, because the access pattern is unpredictable and hard to optimize in hardware. However, it is vulnerable to side-channel attacks. If an attacker can observe which memory addresses are being accessed (through cache timing, for example), they can learn information about the password. This variant is best for settings where the attacker does not have physical or privileged access to the machine.

Argon2i (data-independent): The memory access pattern is determined solely by the parameters (memory size, iterations, parallelism), not by the password. This makes it immune to side-channel attacks because the access pattern reveals nothing about the password. However, the fixed access pattern is slightly easier for specialized hardware to optimize against. This variant is best for settings where side-channel resistance is the priority.

Argon2id (hybrid): Combines both approaches. The first pass uses data-independent addressing (like Argon2i), and subsequent passes use data-dependent addressing (like Argon2d). This provides the side-channel resistance of Argon2i during the critical first pass, when the password is most directly influencing the computation, while gaining the GPU/ASIC resistance of Argon2d in later passes.

RFC 9106 recommends Argon2id as the default choice, and this is what QNSQY uses. It provides the best balance of protection against all known attack vectors.

Why Memory-Hardness Defeats Modern Attackers

Here is how different types of attack hardware fare against Argon2id with 128 MB of memory:

Hardware Cores Memory SHA-256 hashes/sec Argon2id (128 MB) attempts/sec
Laptop CPU 8 16 GB ~30 million ~8
High-end GPU (RTX 4090) 16,384 24 GB ~10 billion ~180
ASIC (Bitcoin miner equivalent) N/A Limited ~100+ trillion Very low advantage

Look at those GPU numbers. With plain SHA-256, a GPU can try 10 billion passwords per second. With Argon2id at 128 MB, it is limited to about 180 per second. That is a reduction factor of over 50 million. The GPU's massive parallel processing power is neutralized because it does not have enough memory to run all its cores simultaneously.

ASICs (Application-Specific Integrated Circuits) are even more extreme. Bitcoin mining ASICs can compute over 100 trillion SHA-256 hashes per second. Against Argon2id, building an ASIC with enough fast memory to achieve a significant advantage would be extraordinarily expensive, erasing the economic incentive for attackers.

How QNSQY Configures Argon2id

QNSQY uses three parameter presets, calibrated for different security needs:

Preset Memory Iterations Parallelism Time to Derive Key
Standard (Free tier) 128 MB 3 4 threads ~1 second
Enhanced (Pro tier) 256 MB 4 4 threads ~2 seconds
Maximum (Pro, customizable) 512 MB 5+ 4 threads ~3+ seconds

Yes, it takes 1 to 3 seconds to derive your encryption key. That deliberate delay is the entire point. Those seconds are the wall that stands between an attacker and your data. To a legitimate user opening their own file, 1 to 3 seconds is barely noticeable. To an attacker trying billions of guesses, it is an insurmountable barrier.

These parameters align with OWASP's Password Storage Cheat Sheet recommendations, which suggest a minimum of 19 MB of memory and 2 iterations for Argon2id. QNSQY's 128 MB minimum is significantly above this floor, providing a comfortable security margin.

Comparing Argon2id to the Alternatives

Algorithm Memory-Hard? GPU Resistance ASIC Resistance Standard
SHA-256 (raw) No None None FIPS 180-4
PBKDF2-SHA256 No Low Low RFC 2898
bcrypt No (4 KB) Medium Medium No formal standard
scrypt Yes High High RFC 7914
Argon2id Yes Highest Highest RFC 9106 (PHC winner)

Argon2id improves on scrypt in several ways: it has a cleaner internal design, better resistance to certain time-memory tradeoff attacks, tunable parallelism, and formal standardization through both the Password Hashing Competition and the IETF.

PBKDF2 and bcrypt are still considered acceptable for many applications, but they offer significantly less protection against modern GPU-based attacks. If you are choosing a password hashing algorithm for a new system, Argon2id is the clear winner.

Understanding the Parameters: Memory, Time, and Parallelism

Argon2id has three main parameters that control how hard it is to compute. Understanding what each one does helps you make informed decisions about the tradeoff between security and user experience.

Memory (m) is the most important parameter. It specifies how many kilobytes of RAM Argon2id must allocate during the computation. More memory means the attacker needs more RAM per attempt, which directly limits how many attempts they can run in parallel. QNSQY uses 128 MB as the minimum, which is well above the 19 MB floor recommended by OWASP. The 256 MB and 512 MB options available in Pro tier provide even stronger protection at the cost of a slightly longer wait.

Iterations (t) controls how many times Argon2id passes over the memory block. More iterations mean more computation time, even for an attacker who has enough memory. Each iteration forces the attacker to spend additional time per guess. The sweet spot depends on what delay is acceptable for the user. QNSQY uses 3 iterations at the 128 MB level, which produces roughly a 1-second delay on modern hardware.

Parallelism (p) specifies how many independent lanes of computation Argon2id uses. This allows the computation to take advantage of multiple CPU cores. Setting parallelism to 4 means four cores work on the hash simultaneously, filling different segments of the memory block. The parallelism parameter does not weaken security; it is an optimization that lets legitimate users complete the derivation faster while the overall work remains the same.

RFC 9106 provides specific guidance for tuning these parameters. The general recommendation is: set memory as high as you can afford (in terms of RAM usage on the user's machine), then increase iterations until the total derivation time reaches your desired threshold (typically 0.5 to 3 seconds for interactive use). Set parallelism to match the number of CPU cores available.

The critical point is that all three parameters should be stored alongside the hash (QNSQY stores them in the encrypted file header). This means you can increase parameters for new files without breaking the ability to decrypt older files that used lower settings.

What About Weak Passwords?

Argon2id cannot save a truly terrible password. If your password is "password123", it is in every dictionary that attackers use. Even at 180 attempts per second (GPU-limited Argon2id), an attacker will find "password123" almost immediately because it is one of the first passwords tried.

But for a reasonably strong password (12 or more characters, not a common phrase or word), Argon2id makes brute-force attacks impractical:

  • A password with 40 bits of entropy (~1 trillion possibilities) would fall to a GPU running PBKDF2 in hours. With Argon2id at 128 MB, it would take years.
  • A password with 60 bits of entropy would take centuries to crack with Argon2id, even with a warehouse full of GPUs.
  • A strong 16-character passphrase with 80+ bits of entropy is beyond the reach of any attacker, period, when protected by Argon2id.

The takeaway: Argon2id dramatically raises the minimum password strength needed to be safe. A "decent" password behind PBKDF2 is vulnerable. The same password behind Argon2id is likely safe. A "good" password behind Argon2id is essentially uncrackable.

Argon2id and Quantum Computers

Password hashing is one area where quantum computers do not drastically change the picture. Grover's algorithm provides a quadratic speedup to brute-force searches, which means it effectively halves the security level. For a password with 80 bits of entropy protected by Argon2id, Grover's algorithm reduces the effective security to about 40 bits of quantum search effort. But Grover's speedup only applies to the search, not to the memory-hardness. Each attempt still requires allocating and filling the full memory block.

In practice, the memory cost is the dominant factor, and quantum computers do not have a known advantage at performing memory-hard computations. The bottleneck is physical memory access, not computation speed.

Sources

  1. RFC 9106: Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications. IETF, September 2021. www.rfc-editor.org/rfc/rfc9106
  2. Biryukov, A., Dinu, D., Khovratovich, D. "Argon2: new generation of memory-hard functions for password hashing and other applications." 2016. IEEE European Symposium on Security and Privacy.
  3. Password Hashing Competition results, July 2015. www.password-hashing.net
  4. OWASP Password Storage Cheat Sheet. cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
  5. RFC 2898: PKCS #5: Password-Based Cryptography Specification Version 2.0. IETF, September 2000. www.rfc-editor.org/rfc/rfc2898

Related Articles

Memory-Hard Password-Based Key Derivation

QNSQY uses Argon2id in all tiers. Argon2id is the winner of the Password Hashing Competition, the OWASP-recommended default, and documented in RFC 9106. Your password derivation does not transit the network.

Try QNSQY

Originally published at quantumsequrity.com/blog/argon2id-explained.