Using a server-wide salt value for all passwords is akin to wrapping your bullet-resistant glass in cellophane. You’ve just taken a reasonably strong, industry-standard security measure and wrapped it in the naivest possible form of security, the good ole’ hard-coded password.

Random salts are intended to prevent a dictionary attack. Nothing more, nothing less. To accomplish this, as well as the side benefit of defeating rainbow tables, they do not need to private or cryptographically strong. It also does not matter if the salt is appended, prepended, or randomly distributed within the original password, as long as the process is repeatable. The point is, if two users have the same password (something crackers frequently try to make use of), they won’t have the same hash. And if someone wants to run a dictionary or even a brute-force attack, they now have to re-run it for every single user.

Most importantly, if you’ve secured your database properly and your hacker does NOT have direct access to every password, then they may try to sniff the password over a network, and assuming your security takes replays into account, a random salt makes the sniffed hash much more difficult to use. I suppose a constant, hard-coded salt provides some security here - unless the hacker happens to be a disgruntled ex-employee who knows what it is, which is actually the most common cause of espionage.

By all means, secure your salts too if you’re paranoid. Put them in a separate table or a separate database or even a separate server. Or even better, use a nonce, or a much stronger scheme like Kerberos. It can’t hurt. But a global hard-coded shared secret is no substitute for a random salt. It’s a feel-good measure, effectively useless and bordering on superstition, but enough for someone to give himself a pat on the back for being more secure.

If you want to be really clever about your salts, then don’t just stick them at the beginning or end; use an algorithm that distributes the salt characters within the original password in a way that’s dependent on the password itself. That way, a 10-character salt is essentially useless to anyone who doesn’t know the distribution algorithm. You’ll get all the benefits of secrecy without sacrificing the security itself.

DeveloperJoe: Encrypt-hash is a useful security measure but I don’t see the advantage of using custom encryption. Unless you’re working in a military sector and have access to bleeding-edge cryptographic tools, I guarantee that your hand-rolled algorithm is much weaker than an industry standard like AES or 3DES or Blowfish. In order to crack one of those schemes, a hacker must first know which one you used, as well as the private key; if he’s able to get all of that information in addition to your password database, I think you’re long past the point where the secrecy of your encryption algorithm can protect you.

brian: That is precisely the point of a random, per-user hash. There are no commonalities to be found after cracking two hashes or n hashes, nor is there any consistent scheme to guess. A cracker HAS to alter his dictionary/hash function for EVERY record.

Ix: Hashing multiple times actually weakens your hash because it raises the probability of collisions. You’re using a “clever” obfuscation, but your hash is still derived solely from the user name and password, which ultimately is just security by obscurity and adds no value beyond what’s offered by just a simple one-time hash. The point of a random salt is that there is no predictable pattern; the information is very little help to a hacker. You can gain a tiny amount of additional security by obfuscating the way in which salts are used, as I mentioned above, but they still have to be random. If you’re substituting any deterministic algorithm for randomness, you’re just making the system LESS secure.

All of these bizarre security implementations amount to a pointless waste of time. It takes about 30 seconds to write 3 lines of C# code to generate a random salt. If you’re generating a whole bunch of them at once and really need crypto-strong salts, another 10 lines or so and a couple more minutes will give you that. How many costly dev-hours have been spent on designing, coding, and testing these pseudo-salts, when it would have taken just a few minutes to put together something much more effective?

Incidentally, I’m betting that a lot of people here are web developers, and if you are, then there’s already a system for dealing with packet sniffers. It’s called SSL. It takes an hour or so and a couple of hundred bucks to deploy. Less, if you don’t mind looking like a cheapskate. Look into it, folks.

We store the salt with each user record in the database, this makes each Salt different. When a user registers, they get a unique ID which we store locally on thier machine and use it to pull the right database record. We then use the salt along with the user’s typed in password to generate the password hash and compare that versus the hash that is stored in the database.

If we can’t find the user, we treat them as a new user and register them. Of course if the user reformats thier machine or logs in on a different machine, then they would have to re-register.

Anyways, that is how we store different Salt on a per user record basis.

Maybe I’m missing something, but doesn’t using even the default account lockout controls in NT/2000/2003 make this process somewhat difficult. Meaning 5 attempts locks it for 30 minutes. If it took even only one hundred attempts, that would be days. Usually a good IPS would pick that up, or a good admin would see the security log go crazy. Secondly, many people are using multiple passwords to layer through a system, and/or multifactor authentication. So, I’m not sure what this really means to me if I have other controls in place.

Another word on salts. I’ll review the two mentioned above, and demonstrate an even more effective method.

The example given in this article would be where a server uses a static salt for all of its passwords, thus, the attacker would need to generate a rainbow table for that server’s specific salt (if they learn the salt). md5(mYs3rV3r1zCo0l + password)

Another example given by one of the first comments is to use a salt unique to the user, such as the hash of the username. md5(md5(username) + password)

HOWEVER, an even better way of using salts is to choose a random number within a range of numbers. This method is quite sophisticated, as it quickly increases the size of an attacker’s rainbow table by many many orders of magnitude, which can take decades of CPU time. The trade-off is the server has to dedicate a relatively short amount of time to brute-force to check if the password is a match.

Example: We randomly pick a number from 31337 to 32337 for every new password; say 31345 this time. That number becomes our salt, and we’ll md5() it to give it 32 bytes of alpha-numeric padding to the password hashed.

md5(md5(31345) + password)

Now, to check if the user entered the correct password, we have to check up to 1000 ‘salted’ passwords until we find a match.

We only have to loop 1000 times (at most), but an attacker would not only require fore-knowledge that our salt ranges from 31337 to 32337, but would also have to also generate 1000 custom rainbow tables instead of just 1.

Cracking hashes offline can be really tedious, that’s why i built http://www.hashhack.com - its an online md5 hash cracker that has over 21 million hashes online, why spend days cracking your hashes when my site can crack them in under 3 seconds ?

For individual users, it is simple to protect yourself - use a password or pass phrase 15 characters or longer. Such a password cannot be stored in NTLM - you will receive a warning when changing to it that ‘the password may not be compatible with older software such as Windows 98.’ NTLMv2 passwords, which do not share this vulnerability, can be up to 128 characters in length.