How to Choose Parameters for KDFs like Argon2, Bcrypt, Scrypt, PBKDF2, Balloon Hashing, & More (Part 1 of 2)

2025-07-01

Most applied cryptographers will at one point or another face the challenge of correctly configuring dozens of obscurely-named KDF security parameters: tt, mm, pp, rr, costα\textrm{cost}_\alpha, σ0\sigma_0, \oint_{‽} (okay, that last one was made up, but you get the point…). On one hand, setting these values too low makes your system vulnerable to brute-force attack. On the other hand, setting them too high creates undue latency for end users, causing frustration and increasing churn. Moreover, as new hardware is released, the “ideal” KDF values are constantly changing and evolving over time!

We, too, faced this dilemma when configuring safe defaults for MFKDF2, so we designed a robust, future-proof methodology that strikes the right balance for any memory-hard KDF. We’re here to systematically solve the problem of KDF parameter selection for you, once and for all.

KDF Parameters

Part one of a two-part series on KDF security parameters.

Introduction

In this piece, we describe a simple, browser-based tool we’ve built to provide up-to-date guidance on how to select parameters for various different key derivation functions (KDFs). This is not only a helpful general resource for the security community, but will be particularly useful for the Multi-Factor Key Derivation Function 2 (MFKDF2), as this scheme allows for updateable parameters without changing the underlying derived key. This means that using MFKDF2 will provide you with a scheme that gets continually harder for attackers over time, without any UX detriment. We’ll discuss this further in a moment. But first, what exactly is a Key Derivation Function (KDF), and why do we want them to be “hard”?

Background on KDFs

KDFs are used when we want to turn a modest source of entropy (often user-supplied, e.g., a password) into a random looking key that can be used for cryptographic operations (e.g., encryption and decryption). KDFs have prolific use in many widely-used systems, such as full-disk encryption (e.g., Bitlocker), logging into websites (e.g., Lastpass), connecting to a WiFi hotspot (e.g., WPA/WPA2).

Hard KDFs

Unlike many computer operations, we actually want certain KDFs to be slow. For instance, the password-based KDFs (PBKDFs) are designed to be tunable so that they can be made slower over time as computers become increasingly fast. The primary reason for the desirable slowdown is to significantly increase the cost and time an attacker must spend to guess a KDF input, such as a password. When a password database is breached, attackers can use high-powered hardware, such as Graphics Processing Units (GPUs) and Application-Specific Integrated Circuits (ASICs), to perform billions of password guesses per second. As soon as attackers are able to reverse these passwords, they can start using them to create chaos, such as by conducting credential stuffing attacks. Given that the average data breach goes undetected for almost 9 months, the more we can slow attackers down in this process, the better.

KDF difficulty comes in two main flavors, and a newer third:

Time-hardness introduces a configurable computational cost, meaning the KDF algorithm is deliberately slow. By increasing a "work factor" or "iteration count," developers can make the process of hashing a single password take a fraction of a second on a standard server. For a legitimate user, this delay is negligible. However, for an attacker attempting to try billions of passwords, this small delay for each guess multiplies into an impractically long time, potentially years or even centuries. This parameter may be referred to as cost, NN, cc, iterations, or tt.

Every KDF can be made time-hard by running the algorithm for multiple iterations. This hardness increase hits every device equally since there is no way of parallelizing around this!

Memory-hardness adds another layer of defense by requiring a significant amount of RAM to compute the hash. This directly counters the parallel processing power of GPUs and ASICs, which have vast computational capabilities but relatively limited and slower memory access per processing unit. By forcing each hash computation to consume a substantial amount of memory, memory-hard KDFs limit the number of parallel guesses an attacker can perform simultaneously, thereby leveling the playing field between the defender's server and the attacker's specialized hardware. In particular, this type of hardness strongly prevents ASICs from being used as ASICs are specialized to running a distinct circuit – so while they may be able to quickly iterate through a hash (e.g., work quickly with time-hardness), they cannot generalize to handle a changing memory parameter! This parameter may be referred to as memory, memory size, mm, block size, or rr.

In essence, these properties ensure that even if an attacker steals a database of hashed passwords, the cost and time required to crack them are prohibitively high, rendering the stolen data of little value.

Parallelization is an additional line of defense that can be used to slow down attackers in a disproportionate manner. Basically, parallelization describes the number of independent threads that should be used to compute the hash. For example, if this was set to two, then operations are roughly twice as quickly computed on two entirely separate threads. Now, for a user that has two threads available, if this took 500ms to compute, then they’re happy, but an attacker may have wanted to use many threads to attack the hash in parallel. In this case, if the attacker had 100 threads to use, they are now getting the effect of 50 when this parameter is set to two. This parameter may be referred to as parallelism, parallelization factor, or pp.

In certain constrained environments such as a web browser, parallelization is not really useful. It will be slower for a user since there aren’t memory-independent threads to access in the browser context. At least, not at the time of writing this.

A Comparative Look at Prominent KDFs

The following are the most popular KDFs in use today, and thus are the ones we are mainly interested in analyzing in this post:

PBKDF2 (Password-Based Key Derivation Function 2)

  • Algorithm: PBKDF2 applies a pseudorandom function, such as a Hash-based Message Authentication Code (HMAC), to the password and a salt for a specified number of iterations.
  • Configurable Parameters:
    • Iteration Count (cc): This is the primary "time-hard" parameter. The higher the number of iterations, the longer it takes to compute the key.
    • Derived Key Length: The desired length of the output key.
    • Pseudorandom Function (e.g., HMAC-SHA256): The underlying hash function to be used.
  • Strengths: PBKDF2 is a long-standing and widely adopted standard (RFC 2898). Its simplicity and the ability to use different hash functions make it versatile.
  • Weaknesses: PBKDF2 is only time-hard and does not have significant memory-hardness. This makes it more susceptible to brute-force attacks using modern GPUs and ASICs compared to newer, memory-hard functions.

Bcrypt

  • Algorithm: Bcrypt is based on the Blowfish cipher. It incorporates a salt and a cost factor into the key setup phase of the cipher.
  • Configurable Parameters:
    • Cost Factor: This parameter logarithmically increases the number of iterations, making it computationally expensive.
  • Strengths: Bcrypt was one of the first KDFs designed to be slow and has been a reliable choice for many years. Its iterative nature makes it resistant to simple brute-force attacks.
  • Weaknesses: Bcrypt's memory usage is fixed and relatively small, meaning it doesn't offer significant memory-hardness. This makes it less resilient against large-scale, custom hardware attacks compared to Scrypt and Argon2.

Scrypt

  • Algorithm: Scrypt was explicitly designed to be a memory-hard KDF. It generates a large vector of pseudorandom data and then accesses it in a pseudo-random order to produce the final key.
  • Configurable Parameters:
    • CPU/Memory Cost (NN): A parameter that increases both the computational and memory costs.
    • Block Size (rr): Affects the memory bandwidth.
    • Parallelization (pp): Allows for adjusting the degree of parallel computation.
  • Strengths: Scrypt's significant memory requirements make it highly resistant to GPU and ASIC-based attacks. It offers a good balance between time and memory hardness.
  • Weaknesses: The high memory usage of Scrypt can be a limiting factor in resource-constrained environments.

Argon2

  • Algorithm: The winner of the 2015 Password Hashing Competition, Argon2 is a state-of-the-art KDF that offers a high degree of resistance to various attacks. It comes in three variants:
    • Argon2d: Maximizes resistance to GPU cracking attacks.
    • Argon2i: Optimized to be resistant to side-channel attacks.
    • Argon2id: A hybrid version that combines the strengths of Argon2d and Argon2i, generally the recommended choice.
  • Configurable Parameters:
    • Memory Cost (mm): The amount of memory (in KiB) to be used.
    • Time Cost (tt): The number of iterations.
    • Parallelism (pp): The number of parallel threads.
  • Strengths: Argon2 is highly configurable, allowing for a fine-tuned balance of time and memory hardness. Its resistance to GPU-based cracking and side-channel attacks makes it the current gold standard for password hashing.
  • Weaknesses: As a more recent and complex algorithm, it may have less widespread library support than older KDFs like PBKDF2 and Bcrypt.

Balloon Hashing

  • Algorithm: Balloon Hashing is a memory-hard KDF with a simple three-step process:
    • Expansion: A buffer of pseudorandom bytes is created from the password and salt.
    • Mixing: The bytes in the buffer are mixed a configurable number of times.
    • Output: A portion of the mixed buffer is extracted as the final key.
  • Configurable Parameters:
    • Space Cost (scosts_\textrm{cost}): The size of the memory buffer.
    • Time Cost (tcostt_\textrm{cost}): The number of mixing rounds.
  • Strengths: Balloon Hashing has provable memory-hardness properties. Its design is simple and elegant, and it is resistant to side-channel attacks because its memory access patterns are independent of the password.
  • Weaknesses: While promising, Balloon Hashing is a relatively new KDF and has not yet achieved the same level of widespread adoption and battle-testing as Argon2 or Bcrypt. This also means that finding audited implementations for your platform may be challenging at the moment.

For new applications, Argon2id or Balloon Hashing are the generally recommended choice, offering the most robust and flexible protection available today.

Argon2 won the Password Hashing Competition and NIST suggests Balloon Hashing in SP800-63b due to its provable security. Still, despite being best-in-class both have known issues that make them weaker in practice than in theory (see “Towards Practical Attacks on Argon2i and Balloon Hashing”).

Multifactor’s KDF Parameter Suggestions

That’s a whole lot of options (and options-within-options) to choose from! Let’s make it easy.

Today we are releasing the first version of our client side “Interactive KDF Benchmark” tool. You can find this tool at https://kdf.multifactor.com, or give it a try below:

Since much of the world’s use of password hashes is for online authentication, we designed this tool for web use.

The flow for your consideration should go as follows.

  1. Consider what a typical client device is for your application (e.g., a few generation old Android phone running Google Chrome)
  2. Determine the maximum latency you believe your users will be comfortable experiencing (e.g., 100ms is typically considered instant, 500ms is likely still “not bad”)
  3. Run the relevant benches on a comparable device with your chosen KDF (suggestions for KDFs above)
  4. The tool will output an optimal parameter set for your given KDF.

At the moment, this tool uses a relatively simple heuristic determined by benchmarking a collection of Argon2 test vectors on an Apple M3 Max 14 core CPU and integrated 30 core GPU. These benchmarks showed the following results:

ConfigurationCPU (c/s real per core)CPU RelativeGPU (c/s real total)GPU RelativeGPU Speedup vs 1 CPU coreMemory (KB)Iterations
t=3, m=40962261.00x2081.00x0.92x4,0963
t=3, m=1638456.30.25x52.60.25x0.93x16,3843
t=4, m=16384*41.70.18x39.30.19x2.83x16,3844

* Approximated from p=3 results divided by 3 for GPU since OpenCL uses parallelism.

In essence, increasing the memory parameter has equal effect for both CPU and GPU, but for a single core, increasing the iterations barely eked out a win. We should note that further analysis will be done with more test vectors and for more hash functions. This was currently available with John the Ripper via OpenCL and OpenMP on the specified machine.

Using with MFKDF2

As a reminder, here at Multifactor, we’re building the Multi-Factor Key Derivation Function v2.0 (MFKDF2), a KDF designed to compose multiple traditional factors (i.e., passwords, HOTP/TOTP, hardware/software tokens, OOBA, etc.) to derive a static key. By design, MFKDF2 is updatable, meaning that after you have initialized and derived a key, you can later reconstitute the factors used to derive the key without changing the key itself. This doesn’t just mean that you can do something like reset your password or create a new TOTP key; it also allows you to actually update the parameters used for the internal KDFs, making them harder to attack over time!

This means that MFKDF2 can provide adaptable security. As the speed of processors increases, or attacks are found on specific hashes/KDFs, you can reconstitute your MFKDF2 policy with heightened security parameters all while deriving the same key. No other KDF alone can boast this feature!

Conclusion

This post and the Interactive KDF Benchmark serve as a vital resource for security practitioners seeking guidance on KDF selection and parameter optimization. MFKDF2 will build upon this foundation, continuously increasing difficulty to ensure a dynamic and robust defense against evolving threats. Our aim is to empower the security community with the tools and knowledge necessary to implement state-of-the-art KDF practices.

Our next steps on this project include:

  • Integrating Balloon Hashing into our list of recommended KDFs.
  • Conducting enhanced benchmarks across a diverse range of devices to refine our decision-making heuristics.
  • Developing an API endpoint to provide easy access to up-to-date parameter guidance, informed by data from multiple devices.

Stay tuned for these exciting updates in Part 2 of this series on enhancing KDF security!

Related Posts

MFKDF2, MFCHF2, & MFDPG2: Next-Generation Multifactor Entropy Stack

MFKDF2, MFCHF2, & MFDPG2: Next-Generation Multifactor Entropy Stack

2025-06-06

MFKDF2, MFCHF2, and MFDPG2 are new user-friendly cryptographic primitives that aim to trustlessly solve the problems of the current authentication and account security.

Introducing Portal: Multifactor's API Gateway Solution

Introducing Portal: Multifactor's API Gateway Solution

2025-05-28

Today, we're excited to announce the release of Portal, Multifactor's brand new serverless, globally-distributed API gateway, available now in early access.

Why Multifactor is a Public Benefit Corporation

Why Multifactor is a Public Benefit Corporation

2025-05-19

Multifactor, Inc. is now officially a Public Benefit Corporation (PBC). Learn more about our commitment to improving computer security and privacy for all.