Does putting salt first make it easier for attacker to bruteforce the hash?

Actually, you are tackling it the opposite way.

It is true that doing hash(salt + password) would allow you to precompute the salt (but see note below) and only hash each password candidate for all those trials. The cost be the same you would bear if you were not using a salt at all.

However, the goal of the salt is not to make bruteforcing a single hash harder, but to ensure that the hashes for different users are different even if they chose the same password and so the cracking effort can't be applied for multiple users.

Let's assume you dumped a PayPal database hashes where they were using MD5 hashes. You want to check passwords 'paypal', 'PayPal', 'PayPal123'...

  1. If they used MD5(password), you can trivially hash any of them and find out if anyone is using such weak password.

  2. If they used MD5(salt + password), you could precompute the partial MD5(salt) for everyone, but still need to hash each password candidate for each user.

  3. If they used MD5(password + salt), you could precompute the partial MD5(password) for each candidate password, and then apply their salt for each user.

#1 is clearly the worst here. You could argue between #2 and #3 based on the different lengths of passwords and salts, as well as the number of users, but I would consider #2 to be preferable. Based on length alone, the enforced minimum length for your passwords is probably higher than the salt size. But I suspect there could be other weakness with the #3 construct, too.

Is it a significant advantage?

Not really.

First of all, many hash functions work in blocks, and the precomputation for values smaller than the block size simply store a copy of the "precomputed bytes". In 99% of the cases the length of both salt and password will be shorter than the block size, so actually there would be no real precomputation being performed. You would need to be using really long strings there for that to be of use.

Additionally, any modern password hash function will at the very minimum use many iterations, if not using more advanced means to make bruteforcing expensive, and your optimization is only applicable the initial iteration.

In any case, rather than simply concatenating salt and password, the most secure way to combine them would be to do an HMAC over them, which mixes them in a better way.


Many recommendations for storing passwords recommend hash(salt + password) rather than hash(password + salt).

Those recommendations are evidently bad, because what they should be telling you is to use a password hashing function that's been specially designed for the purpose, like (in rough order of newer and betterish to older and worse-ish):

  • Argon2 (best)
  • scrypt
  • bcrypt (not bad but beginning to look dated)
  • PBKDF2 (far from ideal but much better than homebrew password hashing)

These functions either:

  1. Take the password and the salt as separate arguments, and thus take care of your question internally;
  2. Give you a higher-level API that takes care of salt generation and management internally:
    • An "enrollment" function that takes a password, generates a salt, and outputs a verification string that encapsulates both salt and hash (e.g., password_hash() in PHP);
    • A "verification" function that takes a password and verification string, and verifies that the password matches the latter (e.g., password_verify() in PHP).

If you're manually concatenating passwords and salts, you're doing it wrong.


That said, it's generally better for a password hashing function to absorb the salt first and the password after. Why? Because that order is generically better at resisting precomputation attacks. In the password-first order, the attacker can precompute the intermediate states that correspond to common passwords, and perhaps there is some clever way of building some sort of big table that exploits this to compute their salted hashes quicker than they could otherwise. Whereas the salt-first order makes this impossible, more so if salts are random.

Doesn't putting the salt first make it much faster for the attacker to bruteforce the password, because they can precompute the state of the hashing function with the bytes of the salt, and then each time of their billions and trillions attempts they only need to finish calculating the hash using the bytes of the password.

No, because the point is that the attacker is not supposed to learn the salts before they steal the password database. That bit of precomputation you mention only gives a tiny speedup relative to the cost of a well-designed password hashing function, and the precomputed state is only good for attacking one individual password entry (assuming no duplicate salts, which is a requirement anyway).

In contrast, with the password-first order, they can:

  • Precompute and store hash function states for large numbers of common passwords before they ever steal the password database;
  • Reuse the precomputed tables across password entries hashed with different salts, even across multiple password databases.

Hash functions recommended for password use do not have this advantage - I'm not sure that any non-trivial hashing functions do, in fact, but wouldn't want to make a blanket statement there.

Instead, hashing functions mix parts from the whole input in each stage. For example, given the input ABCDEFGHIJKLMNOPQRSTUVWXYZ, the first step could be something like pairing the first character with the last, and iterating until no input is left. This would give AZBYCXDWEVFUGTHSIRJQKPLOMN. Assume the "salt" was ABCDEF, and the password was the rest, then change the password to PASSWORD - the output of this example first step would be ADBRCODWESFSPA, which wouldn't help you with the original hash in the slightest.

This is just an example - real hash functions work on binary values, and perform more complex mixing, for a couple of differences - but you can see that it doesn't matter where the salt is for the output to change at a very early point.

There is even a principle (the Avalanche Effect) which suggests that a single bit being changed in the input to a hash function should change about 50% of the output bits, and most hash functions, even ones which are now considered unsafe such as MD5, follow this (while my example above does not!).

Essentially, you can't pre-compute part of a hash in the way you suggest, unless there are other flaws in the system. If you, for some reason, hashed the salt, took the first half of the output, and bolted it onto the second half of the hash of the password for storage, that would introduce the theoretical weakness so you'd only need to compute the hashes of passwords.