There are many questions about picking a hash function, including How to securely hash passwords? or Are there more modern password hashing methods than bcrypt and scrypt?, with very detailed answers, but must of them date quite a bit.

The consensus seemed to be that:

  • bcrypt is a good choice
  • scrypt should be a better choice, but, at the time, it was still a bit new, so one should have to wait to see if it stands the test of time

Argon2 is now the winner of the Password Hashing Competition, but it is definitely still quite new, so the same arguments that applied to scrypt at the time probably apply to it now.


  • Is bcrypt still a good choice?
  • Is scrypt now a good choice?
  • Is Argon2 already a good choice?

Basically, today, for an average system with passwords, which password hashing function should one prefer? For those functions that have parameters, what should they be?


Note that even though the question is a near duplicate of How to securely hash passwords?, as stated above, most answers to that question date back to 2010-2013, with the most recent relevant updates dating back from 2016. Things have obviously changed since then, and what I am looking for is an update to those excellent answers. Feel free to answer with an update in that question and close this one if you think it makes more sense, but please don't just close this one without an up-to-date answer either here or there.

  • 3
    Possible duplicate of How to securely hash passwords? – forest Sep 10 '18 at 2:25
  • 7
    Briefly, Argon2 is recommended now days with the highest parameters you can tolerate. Scrypt is also secure but is less flexible, and bcrypt is better than nothing, but not particularly memory-hard nowadays. – forest Sep 10 '18 at 2:27
  • 2
    @forest The "exception" is what I'm actually looking after. Is it really already recommended? Do others think it has stood the test of time? It's still quite recent. Also in most of those answers scrypt itself was still considered as "quite new". I guess it's not longer the case. What about the current "viable" parameters? – jcaron Sep 10 '18 at 8:15
  • 1
    Yes, it has still stood the test of time. Not to mention, it is standardized. As for "viable parameters", that really depends on you. No matter how things pan out, the answer is always going to be "as high as you can tolerate". – forest Sep 10 '18 at 8:18
  • 1
    @forest bcrypt just being “better than nothing” is quite an understatement, though. Those three algorithms all pretty secure, and unless your attacker is extremely motivated and has a lot of resources, they will all work great. You could even argue that Argon2, and even more so scrypt, still need more analysis before you can safely argue for them to be superior to bcrypt. – caw Sep 17 '18 at 2:13

I do not recommend bcrypt for new designs where the input value is human-generated token (e.g. a password) and offline cracking is in the threat model. The lack of memory-hardness is a serious problem when you consider how powerful commodity hardware is these days. While the lack of any major bcrypt-based cryptocurrencies has not attracted FPGA or ASIC mining implementations for the algorithm, there has still been some interest in attacking bcrypt using hybrid ARM/FPGA SoCs, such as in this paper from 2014. Ultimately, the lack of memory-hardness is a significant problem for modern designs.

scrypt has memory hardness as part of its design, but it has some shortfalls. For a start, there are quite a few scrypt-based cryptocurrencies and this has attracted quite a market for commodity FPGA and ASIC mining solutions that could be repurposed for cracking. Furthermore, scrypt's memory-hardness and iteration count are both tied to a single scalar cost factor. This makes it difficult to tailor scrypt to your own threat model. I recommend scrypt where it is the easiest option for password storage in the language or framework you're using, for example if it is already an inbuilt option for protecting user passwords.

Ultimately, I always recommend Argon2 as the preferred choice, for a few reasons:

  1. It has been around for a while now - it won the PHC in 2015. There have been quite a few papers studying Argon2's security proofs, and many more studying potential ways to accelerate the algorithm on dedicated hardware. So far it has withstood scrutiny very well.
  2. There are open source implementations and bindings for C, Erlang, Go, Haskell, JavaScript, Java, Lua, OCaml, Python, R, Ruby, Rust, C# (both Framework and Core), Perl, Ruby, and Swift.
  3. Argon2 is built around the AES cipher, and most modern x86_64 and ARMv8 processors implement an AES instruction set extension. This helps close the performance gap between the intended system and a dedicated cracking system. (EDIT, Feb 2019: It seems that newer versions of Argon2 may not be compatible with the AES implementation in hardware extensions. See comments for discussion around this)
  4. Argon2 is particularly resistant to ranking tradeoff attacks beyond a memory fraction of one third, making it much more difficult to accelerate cheaply on FPGAs. This is because FPGA-based cracking solutions are mostly limited by memory bandwidth, and with Argon2's design the attacker must swallow a great increase in computational time in order to reduce memory bandwidth requirements, thus making the tradeoff inefficient. You can read more about this in section 5.1 of the Argon2 paper, with information on scrypt available for comparison in table 6 (under section 5) of the paper "Tradeoff Cryptanalysis of Memory-Hard Functions".
  5. Memory-hardness and CPU-hardness parameters are separately configurable, along with a parallelism factor. This allows you to better tailor the security bound to your use-case, such as a server with moderate CPU power and a large amount of RAM.

As you noted, the parameters you choose are important. scrypt doesn't give you much choice, so I recommend picking a cost factor based on time (e.g. 1500ms of processing) in that case.

For Argon2 you have more choices than just parameters. There are in fact three different implementations of Argon2, known as Argon2d, Argon2i, and Argon2id. The first one, Argon2d, is most computationally expensive and resistant to acceleration by GPUs, FPGAs, and ASICs with limited memory bandwidth. However, since the memory accesses of Argon2d are dependent on the password, side-channel attacks that leak information about memory accesses may reveal the password. Argon2i, as its suffix suggests, selects memory addresses independently of the password. This reduces its resistance to GPU cracking, but eliminates the side-channel attack. Argon2id is a hybrid approach wherein the first pass uses the Argon2i (independent) approach, and subsequent passes use the Argon2d (dependent) approach.

Wherever possible you should use an Argon2id implementation. However, this is not always available. For a scenario in which you are protecting passwords on a server and your threat model deems memory access side-channel attacks to be very unlikely (this is most of the time in my experience) you may use Argon2d. If memory access side-channel attacks are deemed to be a potential risk, e.g. in a multi-tenant system where untrusted or less-trusted users run code on the same system that does the Argon2 hashing, then Argon2i may be the better choice.

In short: use Argon2id if you can, use Argon2d in almost every other case, consider Argon2i if you really do need memory side-channel attack resistance.

For the parameters, the only hard rules are for Argon2i, which must be treated specially due to its comparative weakness to the other options. Specifically, the number of iterations must be 10 or more, due to a practical tradeoff attack on Argon2i.

You should tweak the parameters to your own use-case and performance requirements, but I believe the following are acceptable defaults for Argon2id and Argon2d:

  • 512MB of memory
  • 8 iterations
  • Parallelism factor of 8

The speed of this depends on your processor, but I achieved approximately 2000ms on my system.

For Argon2i you must increase the number of iterations to a minimum of 10, which may require you to decrease the memory factor for performance reasons. This is another reason to try to avoid Argon2i unless you absolutely require its resistance to memory access side-channels.

  • Great link to source implementations for platforms that do not supply Argon2! – zaph Nov 13 '18 at 7:44
  • 1
    @MikeSchem While they won't on their own, an adversary with sufficient resources can simply reuse the existing silicon IP to build something that does. It's a massive cost reduction over a brand new design. – Polynomial Nov 13 '18 at 9:14
  • 1
    @MalcolmMacLeod My understanding is that some of the AES-NI instructions are incompatible with Argon2 because of some implementation specifics, whereas other parts of the AES-NI instruction set are still useful, but I agree that the documentation isn't clear on this. I'd have to ask the authors, or someone who has actually implemented it. – Polynomial Feb 23 at 17:26
  • 1
    From further reading I've come to the understanding that earlier versions of argon2 during the competition could make use of AES-NI but that after it was modified this is no longer the case. It is possible I'm mistaken but that is what it seems like to me. Perhaps if we can't get a 100% clarification at least update the answer to state that this is not 100% clear so as to avoid anyone getting the wrong idea without further research. – Malcolm MacLeod Feb 27 at 21:54
  • 1
    How old is Argon2? (How long have experts been trying to crack it?) – jpmc26 Feb 28 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.