The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Hashing passwords

I am creating a site that will have a login system and I would like to hash a users password before storing it in the database. My question is in case a user makes a simple password that could be figured out using brute force methods would it help to hash the password using md5 and sha1 like so:

PHP Code:

md5(sha1($Password));

or would a salt that contains letters and numbers do the trick with just md5 like so:

If by "brute force" methods you are referring to an attacker gaining access to your database's list of hashed passwords and attempting rainbow lookups on them, then either method should adequately secure your users' passwords against this attack. Salting is a tried-and-true, time-honored and recognized method of making hashed data cryptographically secure; double-hashing using multiple algorithms, however, is one that, to my knowledge, has never cryptanalyzed, although logically it makes sense. Maybe combine the methods - salt, then hash, then salt again, then hash again - if you really want to, but salting alone will be sufficient, especially if each user has their own unique salt.

If instead you mean someone sitting at their computer guessing obvious passwords ("password", "pword", "god"...), then nothing you do with a password (short of outright rejecting bad passwords) will secure your users' accounts should they choose such poor passwords.

In my applications, I force users to use at least 2-3 classes of characters (where the "classes" are defined as being lower-case letters, upper-case letters, numbers, and symbols), and then each time the user changes their password (including the initial setting of their password) I give them a new random salt. One method I use for generating salts is:

PHP Code:

$salt = md5(time());

I've also written algorithms that choose from a wider array of possible characters (all 4 of the above-mentioned classes) to generate the salt. Since the user never needs to even see the salt, you can be as creative as you want with generating it.

With the time in the salt how do you go about doing that? When a user goes to log in at a later time does it pull the time of when they created the password from a database to recreate their salt for matching their password to the one in the database?

With the time in the salt how do you go about doing that? When a user goes to log in at a later time does it pull the time of when they created the password from a database to recreate their salt for matching their password to the one in the database?

I think Dan was just indicating a way a salt could be created.

You could have a table called users..

Username | Password | Salt

You could set the salt when they create the account... personally I see no reason for it to ever change unless it has been compromised.

thats my problem with it too. If you're storing the salt with the hash, the salt becomes pointless..

Obviously, a per-user salt is more secure, if you can keep the salts secure but still accessible to your scripts..
I'm not sure how to do that though, right now I keep one salt, in a file in the non public folder of my server that only my scripts have access to.

If you give someone a program,
you will frustrate them for a day;
if you teach them how to program,
you will frustrate them for a lifetime.

Incidentally, this highlights another aspect of my apps: I never check passwords in the database itself, I always pull it out and check them in my app. This saves me from a potential SQL injection that I didn't defend against allowing someone to log in with any username they want.

To address the concern of the Bad Guy(R) getting the salt, it doesn't matter. The salt is never meant to be secret. This is the most misunderstood aspect of salted hashes. The salt is there to negate the use of rainbow tables (a "rainbow table" is a table of all (or most) possible results of a hashing algorithm along with strings that result in that hash; Google it for more information), and the per-user salt is there to complicate brute-force attacks on the entire list of hashed passwords (if you use the same salt for every user, then someone who gets the entire list of hashed passwords can brute-force every password at once - generate a hash, check it against every password, see if anything matches). Per-user salts mean that an attacker has to attack each individual password one at a time, making the entire ordeal computationally infeasible.

I think I will use a single salt for all passwords which will be stored in my code, and use a few methods to hash the passwords so that they are more secure.

Please please please read my last post before you run with this idea. This is an idea born of ignorance of salts, and I do not mean any disrespect at all - so very few people understand salts, and this has lead to the rapid propagation of this fallacy.

Please please please read my last post before you run with this idea. This is an idea born of ignorance of salts, and I do not mean any disrespect at all - so very few people understand salts, and this has lead to the rapid propagation of this fallacy.

A salt stored in code definitely does increase security though. They don't have an additional (VITAL) piece of information to work with.

If someone manages to get your code that has your salt in it as well as your users table, then shame on you and let me know so I NEVER sign up for anything of yours

Off the top of my head, there is [url=http://php.net/mcrypt]mcrypt[/php]

Plus I'm sure phpclasses.org has PLENTY of encryption/hashing classes

Two-way encryption of passwords is a bad idea that leaves your users vulnerable if they use the same username/password for other sites as well (and so very many do). If an attacker gains access to your server's filesystem (something that is depressingly easy to do in many shared hosting environments), then they have your database and your decryption key (since it must be in your scripts in plain text). Not to mention that a slight server misconfiguration could result in dumping your script as plain text, revealing your key as well as any possible security holes to gain access to the list of your users' passwords.

Two-way encryption of passwords is a bad idea that leaves your users vulnerable if they use the same username/password for other sites as well (and so very many do). If an attacker gains access to your server's filesystem (something that is depressingly easy to do in many shared hosting environments), then they have your database and your decryption key (since it must be in your scripts in plain text). Not to mention that a slight server misconfiguration could result in dumping your script as plain text, revealing your key as well as any possible security holes to gain access to the list of your users' passwords.

A moment of ignorance if you will.. hehe. Definitely 2-way passwords is a bad idea.

OK so here is my new plan:
Hash passwords using md5 and sha1 with a salt that is created with a string stored in my code and the time the password is created which shall be stored in the database. This way if someone is able to get the database they are missing part of the salt needed to hash the password properly and if they gain access to my code they are missing the salt time which is stored in the database. Let me know what you all think of this plan.

MD5 produces a 128-bit hash. That is, run some data through it and you will get one of the possible 2^128 (that's roughly 3.40 x 10^38) results. With the now-well-known collision attacks on MD5, this complexity has been reduced to roughly 2^78 (3.02 x 10^23). What that means is that it takes over 300 billion billion (that's not a typo: 300 billion billion) operations to find a word that hashes to the same result.

To further weaken MD5, there are "rainbow tables" that are essentially lists of MD5 hashes along with strings that produce those hashes. These enable someone to take any MD5 hash and find a string that will produce it.

Salting is designed to thwart that second type of attack. Even known (you could put your salt in a giant neon sign if you wanted, it doesn't matter), using a salt guarantees that an attacker cannot simply use a rainbow attack to get your users' passwords. (In fact, in every cryptanalysis of salted hashes, one of the basic assumptions is that the salt is always known.) This means that the attacker has to regenerate those 300 billion billion possible results to get your salted passwords. And if you use unique salts for each user, that means 300 billion billion per user account!!

I suppose the heart of your question is the best method to keep your users' passwords secure should the worst happen, that is, should some Bad Guy(R) break into your server and gain full access to your filesystem. That's simple: use a unique, random, per-user salt; don't use MD5. Generate your salts in whatever manner you wish (I recommend a string of at least 10 characters consisting of upper- and lower-case letters, numbers, and symbols (at the very least those above the numbers on your keyboard)). Then use SHA-256 or SHA-512 (see PHP's hash function). Don't bother with double-hashing unless you really want to (it adds computational time to your application, and although that may not be a concern, there isn't any cryptanalysis to say that you're getting anything in return (which isn't to say that you aren't, just that it's not known if you are or not)). Don't bother with some "secret salt" in addition to your per-user salt: what happens if for whatever reason you lose your script and have no backups? Or you accidentally delete that line and overwrite your backup before you realize the mistake? So long as you store the salt with the user's hashed password and can remember what algorithm you used to generate the hash (that is, what hashing algorithm you used, and whether the salt was prepended or appended), you can always recover from some snafu that would leave all your users locked out with a "secret salt" method.

Incidentally, this highlights another aspect of my apps: I never check passwords in the database itself, I always pull it out and check them in my app. This saves me from a potential SQL injection that I didn't defend against allowing someone to log in with any username they want.

I'm sure I've read this before but this time it really stuck. Thanks for the info!

Just to throw one thought into your discussion - what about generating the salt based on username and password?
This would be relatively unique to each user, reconstructable on login and not stored in any way.

If you have the wrong password the salt is wrong -> authentication against the saved hash fails.
If you have access to database/filesystem -> nothing happens, you can't "dehash" (ok, wrong term, just for simplification) the hashes due to the missing salt and to generate the salt you would have to know the password.