Where do you store your salt strings?

Viewed 88031

I've always used a proper per-entry salt string when hashing passwords for database storage. For my needs, storing the salt in the DB next to the hashed password has always worked fine.

However, some people recommend that the salt be stored separately from the database. Their argument is that if the database is compromised, an attacker can still build a rainbow table taking a particular salt string into account in order to crack one account at a time. If this account has admin privileges, then he may not even need to crack any others.

From a security perspective, is it worth it to store salts in a different place? Consider a web application with the server code and DB on the same machine. If the salts are stored in a flat file on that machine, chances are that if the database is compromised, the salts file will be, too.

Are there any recommended solutions to this?

7 Answers

The point of rainbow tables is that they're created in advance and distributed en masse to save calculation time for others - it takes just as long to generate rainbow tables on the fly as it would to just crack the password+salt combination directly (since effectively what's being done when generating rainbow tables is pre-running the calculations for brute-forcing the hash), thus the argument that by knowing the salt someone could "generate a rainbow table" is spurious.

There's no real point in storing salts in a separate file as long as they're on a per-user basis - the point of the salt is simply to make it so that one rainbow table can't break every password in the DB.

Often, they are prepended to the hash and stored in the same field.

There is no need to store them separately - the point is to use a random salt for each password so that a single rainbow table can't be used against your entire set of password hashes. With random salts, an attacker must brute-force each hash separately (or compute a rainbow table for all possible salts - vastly more work).

If you had a more secure storage location, it would make sense to just store the hashes there.

The point of a salt is to render all rainbow tables useless and require a new set of them to be made. It takes just as long to guess a string as to make a rainbow table. For example the SHA-256 hash of "password" is 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. After a salt is added, such as "badpassword" the new string to be hashed is "passwordbadpassword" which, due to the avalanche effect, dramatically changes the output, to 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

Normally the salt is just stored in the same database as the password, also because if one database is hacked, it is likely that the other will be, also.

The reason why salting is used to prevent the rainbow table attach. Malicious user, who somehow reached the database and sees the hashed passwords, gets the table of most common passwords, find their hash value and look up the passwords in the table.

So when user sends the password, we add randomly generated salt to the password.

 userPassword + salt

and we pass this to our hashing algorighm.

 hash(userPassword+salt)

since salt is randomly generated, userPassword+salt becomes a random value, defintely not one of the most common used passwords. So malicious user will not figure out the what password used by checking the rainbow table.

Now salt value is prepended to the hashing value, because it is used again when user sign-in to compare the passed credentials with the saved credentials.

 hash(userPassword+salt)=ashdjdaskhfjdkhfjdashadslkhfdsdh

this is how this password stored in db:ashdjdaskhfjdkhfjdashadslkhfdsdh.salt

Now if malicious user sees this, he can figure out the password but it will take tremendous amount of time. Because each password will get a different salt. Let's malicious has table of 5000 common passwords and theirs hash.

One important thing, malicious user does not have only one table. Because there are too many different algorithms, so malicious user will have 5000 password's hash values for each algorithms.

now for each password, let's say he starts with the first user's password, he will add that salt to 5000 common passwords and create a new rainbow table for each different algorithm to find only 1 password. Then for the second user's password, he will see a different salt, he will calculate new rainbow tables. It is not even guaranteed, user's password will be in those common password's list.

If you use a library (or make your own one) which uses a fixed size string as the salt, then you can store both the salt and the hashed password in the same field. You would then split the stored value to retrieve the salt and the hashed password to verify the input.

With a salt of 10 characters and a fixed hash size of 40 characters, this would look like this:

salt = "california"
passwd = "wp8tJ4Pr"

stored_passwd = salt + hash(passwd + salt)

salt = substr(stored_passwd, 0, 10)
hashed_passwd = substr(stored_passwd, 10, 40)

if hash(user_input + salt) == hashed_passwd:
    print "password is verified"

Since the whole purpose of a salt is to prevent password attacks with precomputed tables (e.g. rainbow tables), storing the salt along with the hashed password is actually harmless.

Related