Is it safe/wise to store a salt in the same field as the hashed password?

You should store it in a single field. Do not try to divide it into parts.

I know this might seem a bit unintuitive for people coming from a database background, where the modus operandi is to normalize data and using serialized strings is considered an ugly hack. But from a security practice, this makes perfect sense.

Why? Because the smallest unit the individual developer needs to operate on is that full string. That is what the app needs to pass to the hash library to check if a provided password is correct or not. From the developers perspective, the hash library can be a black box, and she need not concern herself with what those pesky parts actually mean.

This is a good thing, because most developers are imperfect humans (I know, because I am one myself). If you let them pick that string apart and then try to fit it all together again they will probably mess things up, like give all users the same salt or no salt at all.

Only storing the parameters in the code is also a bad idea. As processors gets faster, you may want to increase the cost factor in the future. During the migration phase, different passwords will have different cost factors. So you will need information on the password level about what cost factor was used to hash it.


What you're missing is that hashes work on the original data, minus the original string. When you want to validate a string against a hash, you take the supplied string, plus the original hash data (cost, salt, etc) and you generate a new hash. If the new hash matches the old one, the string is then validated (in other words, the string is never decrypted, it is rehashed).

Having the salt doesn't help you brute force. The salt is an essential part of a hash in the same way tumblers are part of a lock. If you take either out, nobody can use it.

Separating storage is pointless. You'll have to reassemble the completed hash to validate it in most cases. That's why all the components are stored in one handy string by default.


Yes, you can store it in a single field, and many databases/applications store the salt+hash in a single field/file etc.

The most famous is Linux (which isn't a DB), that stores the hash in the /etc/shadow file using the format:

"$id$salt$hashed", the printable form of a password hash as produced by crypt (C), where "$id" is the algorithm used. (On GNU/Linux, "$1$" stands for MD5, "$2a$" is Blowfish, "$2y$" is Blowfish (correct handling of 8-bit chars), "$5$" is SHA-256 and "$6$" is SHA-512,[4] other Unix may have different values, like NetBSD.

(source: https://en.wikipedia.org/wiki/Passwd)

The salt is not meant to be secret (or at least not more secret than the hash). Its primary purpose to make brute-forcing attacks much much harder since the attacker has to use a different salt for each individual user.

But your question is more nuanced -- because you're not just asking about salts but parameters as well. Things like the hashing algorithm, iteration count, and salt. In any case, don't store this in code, they still belong in the DB.

Imagine you've got a bunch of users, and you've used SHA1 as your hashing algorithm. So your database field would be something like SHA1:SALT:HASH.

If you wanted to upgrade your Database to BCRYPT, how would you do this?

Typically you'd deploy some code so that when a user logs on, you verify the password, and if valid -- you'd re-hash the password with a newer algorithm. Now the field for the user looks like this: BCRYPT:SALT:HASH.

But then some users would be on SHA1, and others on BCRYPT, and since this is at a user level, you need the parameters that tell your code which users are which to be in the Database.

In short, storing the parameters and hash in a single field is OK, but splitting them out for whatever reason (efficiency, easier code etc) is also OK. What's not OK is storing this in your code :)

TL:DR

Troy Hunt recently published a podcast suggesting that instead of migrating to BCRYPT in the manner above, it's more effective to simply take all the SHA1 hashes currently in the DB, and hash them using BCRYPT.

Effectively BCRYPT(SHA1(clear_password))

When a user logs on you'd

BCRYPT(SHA1(clear_password)) == <db_field>

This way, everybody on the platform gets upgraded at once, and you don't have a database with multiple hash formats for passwords. Very clean and very nice.

I think this idea makes perfect sense, but even though everyone migrates at once, it's not instantaneous. Unless you're willing you accept some downtime on the app (while you re-hash all the passwords), there will still be a small gap of time where some users are on BCRYPT and some on SHA1, hence your DB should still store the parameters of the hashing algorithm, and your code would execute based on it.