Does anybody not store salts?

Not storing the salt is bad advice.

The main purpose of a salt is that each user password has to be attacked individually.

If you do not store the salt then, as you said, you need to try every single salt combination in order to validate the password. If you need to check every single salt combination, this means that the salt cannot be too long (you mentioned 12 bits in a comment). If the salt is not long, it means that the salt will be repeated for many users. If it's repeated for many users, it means the attacker will be able to attack many users at the same time, which will save the attacker time.

By doing that, you nearly completely defeat the purpose of using a salt.


A 'secret' salt is known as a pepper.

From Wikipedia:

A pepper can be added to a password in addition to a salt value. A pepper performs a similar role to a salt, however whereas a salt is commonly stored alongside the value being hashed, for something to be defined as a pepper, it should meet one of the following criteria that define it a more carefully hidden 'secret' than the salt value:

  • The pepper is held separately from the value to be hashed
  • The pepper is randomly generated for each value to be hashed (within a limited set of values), and is never stored. When data is tested against a hashed value for a match, this is done by iterating through the set of values valid for the pepper, and each one in turn is added to the data to be tested (usually by suffixing it to the data), before the cryptographic hash function is run on the combined value.

The advantage of a pepper is that an attacker must now guess up to the number of possible permutations of a pepper value for each plaintext entry.

Peppers increase the length of attack for a specific hash, whereas a salt does not.

Remember that a salt is an effective mitigation for precomputed hashes and it makes an attacker spend a long time attacking a set of hashes. However, if only one hash is of concern, and no precomputed hashes are to be used, a salt does not increase the length of attack. A Pepper however, forces the attacker to use multiple guesses for each plaintext password, even for a single hash.

In this way, a pepper is similar to key stretching.

Most implementations prefer key stretching to peppers.

My personal observation is that most implementations prefer key stretching to peppers. I don't have a reference for this so readers may provide supporting or dissenting references in the comments. People tend to prefer key stretching because it has a known and expected performance cost and security benefit. In order to compute the Nth round of a hash, N hashes must be computed. With a pepper however, only the expected number of attempts can be calculated. Consider a 1 byte pepper, the attacker would need 256 guesses to guess all possible combinations, but the expected value is 128, and the attacker could (on average of 1/256 times) guess the value on the first try.

Peppers and Key Stretching can work against each other.

Key stretching is effective because you can set the number of rounds based on the length of time you want the computation of a hash to take. Say you want a single check to take half a second on current hardware, you just increase the rounds until that occurs.

With a pepper, because you need to guess multiple values for each password, the size of a pepper must be inversely related to the number of rounds in order to keep the computation time constant.

Practical advice on hash implementations

The best advice for password/hash implementations is to use well known methodologies and tested libraries. You should be using bcrypt or pbkdf2 with a unique salt and many rounds. These algorithms tend to have well known implementations in many languages and frameworks. If you happen to find a well known and tested library that includes a pepper, in addition to salts and key stretching, it may be worth your while to use it, but the additional benefit often outweighs the performance costs.


Background: You should be using a Slow Password Hash. (i.e. bcrypt) By 'slow' I mean computationally expensive, taking more than 100ms (on your hardware) with DoS protection * to test a single password. This is to increase the processing power needed (on attacker hardware) to find the password by brute force, should the hash be stolen.

Per-user unique salt is highly recommended. (in the case of bcrypt it is automatically generated) Salt should be highly unique (i.e. long & random), but not secret. Using unique salt means an attacker would have to run a separate brute force Job for each user.

If there were 'no salt', the attacker could instantly use a Rainbow Table and no brute force at all.

If you use a 'shared salt' only, then an attacker could crack passwords for all users with a single brute force Job. (not as quick as a rainbow table but still much easier than a separate brute force Job for each one)


Answer: If you were to 'not store' the salt ('brute force the hash at runtime' as your professor suggests)

  • the possible salts would have to be very few
  • the hash would have to be quite a bit faster

This would totally defeat the purpose of Salt, severely cripples the benefit of a Slow hash. That is a major design mistake on the part of your professor. Basically, he is rolling his own password storage scheme, where he should be using the well vetted bcrypt algorithm (or scrypt or PBKDF2) as it was intended to be used.


* As @Navin commented, this would be a potential DoS attack vector. One solution is to limit the number of hourly attempts per IP, and per username. It is also possible that you should reduce the 'slowness' of your hash to only take 10ms. This is not nearly as good as 100ms from a 'stolen hash' perspective, but still way better than 'microseconds'.