Login or create a free accountShare your thoughts!
tristen Photo
tristen (Site Newb) wrote 1 week ago
Hey Andrew,

All makes sense, thanks for the info!

Tristen
Andrew Photo
Andrew Johnson (ITNewb Guru) wrote 1 week ago
Hey Tristen, welcome to the site.

As I'm sure you're well aware, one-way hashing algorithms produce identical output given the same input. Two-way encryption such as my cryptastic class, on the other hand, can produce unique output given the same input. With this in mind, our goal in using a one-way hashing algorithm is to produce a hash that is computationally very difficult, in terms of the time it takes to crack the hash. This is why the pbkdf2 performs so many iterations.

If an attacker is able to gain access to both the processing server (such as a web server) and the storage server (database) they will in most cases be able to easily crack the passwords, in the same way you're "checking" passwords. Without crypto hardware/devices this is just the way it goes. If security is extremely important and you have to the play the game with the deck stacked against you, so to speak, all you can do is make it as difficult and time consuming as possible for an attacker to obtain the necessary pieces of the equation to crack your passwords. This gives you time to detect and respond to the intrusion, thereby limiting the damage caused.

An attacker will want to figure out a few things. What hashing algorithm(s) is being used? Is a salt being used and if so, what is it? How many iterations are being performed? Is the salt embedded in the stored hash? So on and so forth. You will have to investigate your system(s) to determine how easily an attacker can obtain this information. If an attacker penetrates your web server and they're able to view your source code, they'll obtain all of this information except the hash itself. Then we have to ask the question, can the attacker easily query the database from the web server to obtain the hashes? Etc, etc, etc...

After taking a look at your code, I see you're using a unique salt for each hashing process. This is good in the sense it reduces the chances of two identical hashes being stored in the database by users who have the same password and it also makes it that much more difficult to crack passwords in certain cases.

However, by storing the plain text salts appended to the hashes, you're losing a good deal of the gain. If the attacker is very good, they'll be knowledgeable with hashing, encryption and so on. They'll take one look at that long hash and possibly discern a salt is being stored in it. It also won't be all that difficult for them to figure out what kind of hashing process is being used, even if it's a somewhat "custom" mix and match.

The big danger I'm seeing here is storing the plain text salt. I would not do that. You'd be better off in my opinion using a static salt that doesn't have to be stored along with hashes.

What I would say is 1) do everything you can to protect your web server (keep it patched, write secure code, and have your web app source code encrypted and anything else that will make it difficult for an intruder to get a look at the actual source) and 2) don't store plain text salts in your database.

One other thing is that you might want to use a less obvious iteration count for pbkdf2, such as 20123 or some such. I hope I've been of some assistance.

Cheers!
tristen Photo
tristen (Site Newb) wrote 1 week ago
Hi Andrew,

Thanks for the article, quick question: is this hash sufficient to store in the database as is, or would you suggest that a random salt also be added for increased security?

For example (note, haven't tested this code...just pseudo code):
  1.  
  2. $pass = 'users password';
  3.  
  4. // create a 16 character random string
  5. $salt = random_salt_function(16);
  6.  
  7. // hash pass along with the salt, and add salt to end of hash
  8. $hash = pbkdf2($pass . $salt, $salt, 1000, 32) . $salt;
  9.  
  10. // store this in the database
  11.  


And when the user attempts to log in:
  1.  
  2. // get hash from database
  3. $pwHash = get_hash_for_user('username');
  4.  
  5. // extract the hash portion
  6. $origHash = substr($pwHash, 0, 32);
  7.  
  8. // extract the salt
  9. $salt = substr($pwHash, 32);
  10.  
  11. // create a hash based on supplied pass word
  12. $newHash = pbkdf2($pass . $salt, $salt, 1000, 32);
  13.  
  14. if($origHash != $newHash)
  15. {
  16.  // fail login
  17. }
  18.  


Is this overkill with the pbkdf2 algorithm?

Thanks,

Tristen
Andrew Photo
Andrew Johnson (ITNewb Guru) wrote Nov 22, 2009
Hey sonofsuns,

I'm guessing you meant to comment on the mcrypt article, not this one... For older versions of PHP you're right, but as far as newer versions it shouldn't be necessary.

Note: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically.

I should have put it though, with a comment. Thanks for bringing this up.

  1. srand( (double)microtime()*1000000 ); // needed for PHP < 4.2.0

sonofsuns Photo
sonofsuns (Site Newb) wrote Nov 22, 2009
Hi,

please don't forget to initialize the random number generator when using mcrypt_create_iv in connection with MCRYPT_RAND.

php.net:

Note: When using MCRYPT_RAND, remember to call srand() before mcrypt_create_iv() to initialize the random number generator; it is not seeded automatically like rand() is.

Otherwise, great class!
joelvardy Photo
Joel Vardy (Site Newb) wrote Sep 22, 2009
Hiya Rocky, there is a lot of information regarding encryption methods built into mysql here : http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html

This article is specifically looking at php functions, which are not transferable through mysql, if you are using php to connect to your database I would consider encrypting and decrypting strings outside of the mysql query.

this could be as simple as:
  1. $password = $_POST['password'];
  2. $password = pbkdf2($password , 'some salt here', 1000, 32);
  3. $query = "select * from `users` where `password` = '$password'";


Hope this is what you meant, Joel
Roky Photo
Roky (Site Newb) wrote Sep 22, 2009
What about MySQL support? It is nice when you can do select like SELECT MD5('smt')

Requirements

Nickname
  Remember me.
Login
Close