It's equivalent of attacking md5('deliciously-salty-'), since the password can be known, e.g., by using the hash from their own account.
Attacking md5 is not really that hard, nowadays - the article mentions 180 billion tries/second.
Yes, it requires a rig with 25 GPUs, but this is almost the perfect use for the "cloud" - you can rent those for a few bucks just for a specific attack. There are even dedicated services nowadays, with no programming knowledge required - you just submit the hashes, and out come the found passwords.
You want to assume that the attacker has the implementation details, but not the associated secret. Assume that the attacker has a stolen copy of the login database with usernames and hashed passwords, and a copy of the login code (pretend the attacker is a rogue developer or you're using an opensource web framework and anyone can view the login code on github). The only thing he doesn't know is the password to enter on the login page to get a hashed password that matches what's in the database.
So, the attacker knows which of those formats in your comment is being used. With no salts, the attacker can just start running md5 against every character string, and look for matches in your database. Adding salts means he has to do that for every character string appended to the specific salt, so he has way more work to do. But, md5 is still really fast, so that extra work is still feasible.
Adding scrypt/bcrypt/PBKDF2 means he has to use a slow hash function multiple times for each possible password he's trying. That means it takes significantly longer for the attacker to try a potential match, which is the goal.
That's true, but once you discover the salt pattern used, then you can crack a specific password and look for the resultant hash in the database. The idea is to use a random salt per password to close this attack vector. That way, even if you do guess the password and you have the salt, the resultant hash is only useful for that one password, even if the same clear-text password is used in other hashes.
Think about it: adding a known global salt to each password in the same manner before hashing is effectively the same (in the long run) as not salting. Once the attacker figures out the pattern you used, he can proceed to crack specific passwords, then search for the resultant hashes in the database.
What I don't understand (truly--I'm a curious neophyte here) is why a random number would be better than salting with, say, their username.
If the assumption is that the random number is known, per both guidelines that only the user-given secret can be assumed secret and that the article says it could conceivably be stored plaintext, isn't it effectively equivalent to just another username?
If two websites use this scheme and they both get hacked and a user has an account on both with the same username/password the attacker has to do half as much work. Another reason is an attacker can compute a rainbow table prior to getting access to the hashed passwords. This would reduce the amount of time the owners of the site would have to respond in the event of a breach. Finally, it's really easy and cheap to generate a random salt.
You can, but it prevents you from allowing changing the username (which might be fine, but why tie yourself?) and it provides less entropy - a username + password can be small enough to fit in a rainbow table, while a random salt can have whatever size you want.
Excellent explanation. I'll further this by adding that, in my use of the excellent PBKDF2.NET library, I generate a salt with the same number of bits that the hashing algorithm generates (e.g., 256-bit salt for SHA256). I can't remember where I read that this was a good practice, though. :(
Why not combine the two approaches? If you have a global salt stored either with your app on a separate server you make the attack require getting access to not only the database, but your global salt as well. A global salt on its own is clearly inferior, but at least to me combined with a unique per user salt should at least offer comparable if not better security.
Attacking md5 is not really that hard, nowadays - the article mentions 180 billion tries/second.
Yes, it requires a rig with 25 GPUs, but this is almost the perfect use for the "cloud" - you can rent those for a few bucks just for a specific attack. There are even dedicated services nowadays, with no programming knowledge required - you just submit the hashes, and out come the found passwords.