doubledee Posted January 29, 2012 Share Posted January 29, 2012 What do I need to do to *safely* capture and store User Passwords in a Registration Form? There was a thread that I started a few months ago where someone had given a really good response talking about "Salt" and so on, but for the life of me I cannot find that info. Nonetheless, I need some help getting my head back into this topic! My Registration Form is complete, and the last thing I need to do is make sure Users enter a "Strong Password" and then I need to store that somewhere, somehow, in the most *secure* manner possible... Thanks, Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/ Share on other sites More sharing options...
php.ajax.coder Posted January 29, 2012 Share Posted January 29, 2012 Store them using a one way hash 'md5' or more secure 'sha1' <?php $pswd = md5('password'); $pswd = sha1('password'); ?> Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312330 Share on other sites More sharing options...
soos Posted January 29, 2012 Share Posted January 29, 2012 A Salt is a small string containing random characters that are not known by the user. But you can use both md5() and salting to safely secure your users passwords. Example: <?php $pass = mysql_real_escape_string($_POST['password']); $salt = 'b7lLkm755246zZlaBkl44zc2'; $password = md5($salt . $pass); $sql = mysql_query("INSERT INTO table (password) VALUES ('$password')"; ?> What the code above does is it first escapes special characters in the string/user's password. Then it md5's the Salt you created along with the user's password, hence it makes the password virtually impossible to crack. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312337 Share on other sites More sharing options...
scootstah Posted January 30, 2012 Share Posted January 30, 2012 md5() and sha1() are garbage for storing passwords. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312389 Share on other sites More sharing options...
Drummin Posted January 30, 2012 Share Posted January 30, 2012 I don't understand the reasoning behind salt. To keep it simple, let's say the password is "Jim" and salt is "1234". These are combined to "1234Jim" (putting salt in front), then encoded. When a person logs in they add password "Jim" it's added to the salt, encoded and passed for query. My point is, all they're doing is entering "Jim" and so how is salt helping to secure things? Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312394 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 I don't understand the reasoning behind salt. To keep it simple, let's say the password is "Jim" and salt is "1234". These are combined to "1234Jim" (putting salt in front), then encoded. When a person logs in they add password "Jim" it's added to the salt, encoded and passed for query. My point is, all they're doing is entering "Jim" and so how is salt helping to secure things? I believe there is a concept of "Rainbow Tables" where hackers store common passwords and use "Dictionary Attacks". So, "password" might be in the "Rainbow Table" and thus an easy choice, but "623901password" would NOT be in the "Rainbow Table" and thus slightly more secure. Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312397 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 mysql_real_escape_string($_POST['password']); What is the benefit of using mysql_real_escape_string()?? Is it really necessary?? Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312398 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 md5() and sha1() are garbage for storing passwords. And so you recommend WHAT instead?? Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312399 Share on other sites More sharing options...
soos Posted January 30, 2012 Share Posted January 30, 2012 mysql_real_escape_string($_POST['password']); What is the benefit of using mysql_real_escape_string()?? Is it really necessary?? Debbie From W3schools: The mysql_real_escape_string() function escapes special characters in a string for use in an SQL statement The following characters are affected: \x00 \n \r \ ' " \x1a This function returns the escaped string on success, or FALSE on failure. It basically 'escapes' characters from being inserted to your queries and preventing somewhat sql injection. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312404 Share on other sites More sharing options...
darkfreaks Posted January 30, 2012 Share Posted January 30, 2012 What you should do Use a cryptographically strong hashing function like SHA-1 or even SHA-256 (see PHP’s hashfunction). Use a long and random salt for each password. Use a slow hashing algorithm to make brute force attacks near impossible. Regenerate the hash every time a users logs in. Example: <?php $username = 'Admin'; $password = 'gf45_gdf#4hg'; // Create a 256 bit (64 characters) long random salt // Let's add 'something random' and the username // to the salt as well for added security $salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username)); // Prefix the password with the salt $hash = $salt . $password; // Hash the salted password a bunch of times for ( $i = 0; $i < 100000; $i ++ ) { $hash = hash('sha256', $hash); } // Prefix the hash with the salt so we can find it back later $hash = $salt . $hash; /* Value: * e31f453ab964ec17e1e68faacbb64f05bccceb179858b4c482c1b182ff1e440e * f1e10feb5b86c6d367e4eb8f90f2cde5648a7db3df8526878f20a77eed00c703 */ ?> Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312405 Share on other sites More sharing options...
Pikachu2000 Posted January 30, 2012 Share Posted January 30, 2012 And to answer your question about mysql_real_escape_string(), it's neither necessary nor desirable to use it on a string that will be hashed. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312407 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 From W3schools: The mysql_real_escape_string() function escapes special characters in a string for use in an SQL statement The following characters are affected: \x00 \n \r \ ' " \x1a This function returns the escaped string on success, or FALSE on failure. It basically 'escapes' characters from being inserted to your queries and preventing somewhat sql injection. I use Prepared Statements, so I don't believe that I need to worry about that. Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312416 Share on other sites More sharing options...
scootstah Posted January 30, 2012 Share Posted January 30, 2012 I don't understand the reasoning behind salt. To keep it simple, let's say the password is "Jim" and salt is "1234". These are combined to "1234Jim" (putting salt in front), then encoded. When a person logs in they add password "Jim" it's added to the salt, encoded and passed for query. My point is, all they're doing is entering "Jim" and so how is salt helping to secure things? Salts mean that multiple users with the same password will have different hashes, therefore making rainbow tables useless (you would have to create a rainbow table for each user). md5() and sha1() are garbage for storing passwords. And so you recommend WHAT instead?? Debbie A longer, slower hashing algorithm. Like SHA512 or bcrypt. From W3schools: The mysql_real_escape_string() function escapes special characters in a string for use in an SQL statement The following characters are affected: \x00 \n \r \ ' " \x1a This function returns the escaped string on success, or FALSE on failure. It basically 'escapes' characters from being inserted to your queries and preventing somewhat sql injection. I use Prepared Statements, so I don't believe that I need to worry about that. Debbie You don't. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312417 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 What you should do Use a cryptographically strong hashing function like SHA-1 or even SHA-256 (see PHP’s hashfunction). Is SHA-1 good enough? Some people say it can be hacked. Use a slow hashing algorithm to make brute force attacks near impossible. What do you mean? Regenerate the hash every time a users logs in. You mean generate a new Hashed Password every time they log in??? Example: <?php $username = 'Admin'; $password = 'gf45_gdf#4hg'; // Create a 256 bit (64 characters) long random salt I thought there were 8-bits in a byte and that a character was a byte? // Let's add 'something random' and the username // to the salt as well for added security $salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username)); Why all the craziness?! Also, is this a concern... http://dev.mybboard.net/issues/843 // Prefix the password with the salt $hash = $salt . $password; // Hash the salted password a bunch of times for ( $i = 0; $i < 100000; $i ++ ) { $hash = hash('sha256', $hash); } Why even more craziness??? One thousand times?! // Prefix the hash with the salt so we can find it back later $hash = $salt . $hash; What do you mean? Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312421 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 I don't understand the reasoning behind salt. To keep it simple, let's say the password is "Jim" and salt is "1234". These are combined to "1234Jim" (putting salt in front), then encoded. When a person logs in they add password "Jim" it's added to the salt, encoded and passed for query. My point is, all they're doing is entering "Jim" and so how is salt helping to secure things? Salts mean that multiple users with the same password will have different hashes, therefore making rainbow tables useless (you would have to create a rainbow table for each user). I don't think that is correct. If you and I both had "santa_claus" for our passwords, wouldn't the same Hash generate DIFFERENT hashed values 99.999% of the time regardless of whether a Salt was used? I think the Salt prevents Rainbow Tables and Brute FOrece Attacks, but has nothing to do with people having the same passwords... md5() and sha1() are garbage for storing passwords. And so you recommend WHAT instead?? Debbie A longer, slower hashing algorithm. Like SHA512 or bcrypt. What do you mean by "slower hashing algorithm"?? Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312426 Share on other sites More sharing options...
darkfreaks Posted January 30, 2012 Share Posted January 30, 2012 bcrypt uses the Eksblowfish algorithm to hash passwords. While the encryption phase of Eksblowfish and Blowfish are exactly the same, the key schedule phase of Eksblowfish ensures that any subsequent state depends on both salt and key (user password), and no state can be precomputed without the knowledge of both. Because of this key difference, bcrypt is a one-way hashing algorithm. You cannot retrieve the plain text password without already knowing the salt, rounds and key (password). Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312429 Share on other sites More sharing options...
scootstah Posted January 30, 2012 Share Posted January 30, 2012 I don't understand the reasoning behind salt. To keep it simple, let's say the password is "Jim" and salt is "1234". These are combined to "1234Jim" (putting salt in front), then encoded. When a person logs in they add password "Jim" it's added to the salt, encoded and passed for query. My point is, all they're doing is entering "Jim" and so how is salt helping to secure things? Salts mean that multiple users with the same password will have different hashes, therefore making rainbow tables useless (you would have to create a rainbow table for each user). I don't think that is correct. If you and I both had "santa_claus" for our passwords, wouldn't the same Hash generate DIFFERENT hashed values 99.999% of the time regardless of whether a Salt was used? No. If you MD5 "santa_claus" it's always going to be the same hash, unless a salt is used. I think the Salt prevents Rainbow Tables and Brute FOrece Attacks, but has nothing to do with people having the same passwords... Without using a salt all you need is a rainbow table and you can easily reveal passwords based on their hash. If multiple people have the password "santa_claus", then multiple people will have identical hashes. This cuts down on the amount of work required to uncover passwords, because they can reveal multiple passwords with a single hash. Using salts means that rainbow tables are only effective if you create one for each individual user with their unique salts. Obviously, this would require considerable time and resources... rainbow tables are quite large. md5() and sha1() are garbage for storing passwords. And so you recommend WHAT instead?? Debbie A longer, slower hashing algorithm. Like SHA512 or bcrypt. What do you mean by "slower hashing algorithm"?? Debbie MD5 and SHA1 are not secure password storing hashes because they are fast. A modern computer can generate MD5 or SHA1 hashes very, very fast. Which means that finding collisions takes hours and not years. A slower algorithm (like sha512 or bcrypt) takes considerably more time to compute and is therefore more secure. Creating rainbow tables or finding collisions would take a very long time compared to md5 or sha1. Coupling this with hash_hmac should be good enough for most applications. hash_hmac makes use of a cryptographic key when making hashes. What this means is that in order to use rainbow tables or brute force hashes the attacker would also need the cryptographic key residing in the file system. So not only does the attacker need to compromise the database, but the file system as well. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312431 Share on other sites More sharing options...
Pikachu2000 Posted January 30, 2012 Share Posted January 30, 2012 I don't understand the reasoning behind salt. To keep it simple, let's say the password is "Jim" and salt is "1234". These are combined to "1234Jim" (putting salt in front), then encoded. When a person logs in they add password "Jim" it's added to the salt, encoded and passed for query. My point is, all they're doing is entering "Jim" and so how is salt helping to secure things? Salts mean that multiple users with the same password will have different hashes, therefore making rainbow tables useless (you would have to create a rainbow table for each user). I don't think that is correct. That actually is correct, provided a unique salt is used for each user. If you and I both had "santa_claus" for our passwords, wouldn't the same Hash generate DIFFERENT hashed values 99.999% of the time regardless of whether a Salt was used? No, a hashing algorithm will generate the same value for the same string every time. That's why salts should be unique. I think the Salt prevents Rainbow Tables and Brute FOrece Attacks, but has nothing to do with people having the same passwords... Salts help prevent "reverse engineering" of the hash values in your database in the event a malicious user was to obtain the data vie a SQL injection attack, etc. Hashes cannot be "decrypted" per se, but there are rainbow tables that hold the hash values that correspond to common dictionary words, names, places, etc. Then the malicious user simply has to compare the hashes to the table to find values that match. A brute force, or dictionary attack is not protected against by salting the hashes stored in the database. Since the mailcious user is simply guessing at passwords, then submitting them to your processing script, this is no different than a user entering their password in your login form; the salt is applied after that. This is where using a slower hashing algorithm comes into play. If md5() runs in 1/10000 of a second, the attacker could theoretically try 10000 passwords in a second and see if any of them work, or 36 million in an hour. If SHA512 takes 1/50 of a second to run, the attacker could only try 180,000 in an hour. Adding a sleep() delay in the login script makes it even less convenient for an attacker to try to guess passwords. Of course, you should utilize an account "lockout" feature in the event a user fails to authenticate x number of times in row, or within a certian time period. md5() and sha1() are garbage for storing passwords. And so you recommend WHAT instead?? Debbie A longer, slower hashing algorithm. Like SHA512 or bcrypt. What do you mean by "slower hashing algorithm"?? Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312434 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 <?php $username = 'Admin'; $password = 'gf45_gdf#4hg'; // Create a 256 bit (64 characters) long random salt // Let's add 'something random' and the username // to the salt as well for added security $salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username)); // Prefix the password with the salt $hash = $salt . $password; // Hash the salted password a bunch of times for ( $i = 0; $i < 100000; $i ++ ) { $hash = hash('sha256', $hash); } // Prefix the hash with the salt so we can find it back later $hash = $salt . $hash; ?> How do I log back in the User? I have a "create_account.php" script with your suggested code above and a "log_in.php" script. As far as I can see, I need to pass the $salt to the "log_in.php" script, because if I calculate it in the 2nd script, then it will always be different due to this... uniqid(mt_rand() Also, I am not quite getting what I should be storing in my database... Thanks, Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312459 Share on other sites More sharing options...
scootstah Posted January 30, 2012 Share Posted January 30, 2012 Of course you'll need the salt, that's the whole point. You need to store the salt in the users table and retrieve it when they try to log in. There's a plethora of tutorials out there that demonstrate this. In fact I think there was a few other topics on the matter not too long ago on these forums. Also, keep in mind that hashing a hash 100,000 times isn't doing any good at all except waste server resources. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312460 Share on other sites More sharing options...
KevinM1 Posted January 30, 2012 Share Posted January 30, 2012 IIRC, hashing an already hashed value actually increases the chances of collision. Could be wrong, but Ii think I read that somewhere. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312476 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 Of course you'll need the salt, that's the whole point. You need to store the salt in the users table and retrieve it when they try to log in. There's a plethora of tutorials out there that demonstrate this. In fact I think there was a few other topics on the matter not too long ago on these forums. Care to share any links? Also, keep in mind that hashing a hash 100,000 times isn't doing any good at all except waste server resources. Yeah, I wonder about that... Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312478 Share on other sites More sharing options...
KevinM1 Posted January 30, 2012 Share Posted January 30, 2012 How hard is it to figure out? You've seen how to create a salt and salted and hashed password. You store those in the users table along with the rest of their info upon registration. For login (pseudocode): if entered username exists in the db: retrieve salt and password for that username if salt + entered password == retrieved password: log user in else: bad password else: bad username Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312481 Share on other sites More sharing options...
scootstah Posted January 30, 2012 Share Posted January 30, 2012 This should get you started... users table CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(30) NOT NULL, `password` char(128) NOT NULL, `salt` char(10) NOT NULL, PRIMARY KEY (`id`) ) the hashing function function hash_password($password, $salt = null) { if (!is_null($salt)) $salt = substr(sha1(uniqid(mt_rand(), true)), 0, 10); // this should be a long, random string // stored somewhere safe $key = 'abcdef'; $hash = hash_hmac('sha512', $password, $key); return array($hash, $salt); } register.php if (!empty($_POST)) { $username = $_POST['username']; $password = $_POST['password']; if (!empty($username) && !empty($password)) { list($hash, $salt) = hash_password($password); // INSERT INTO users VALUES (0, $username, $hash, $salt); } } login.php if (!empty($_POST)) { $username = $_POST['username']; $password = $_POST['password']; if (!empty($username) && !empty($password)) { // SELECT username, password, salt // FROM users // WHERE username = $username // $row = fetch row list($hash) = hash_password($password, $row['salt']); if ($hash == $row['password']) { // hashes match, log in } } } IIRC, hashing an already hashed value actually increases the chances of collision. Could be wrong, but Ii think I read that somewhere. Yeah, I remember reading a big article about why it was bad. But in my 47 seconds of Googleing for it, couldn't find it. Oh well. Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312482 Share on other sites More sharing options...
doubledee Posted January 30, 2012 Author Share Posted January 30, 2012 scootstah, Why would I want to use your approach using hash_hmac versus what DarkFreaks proposed last night with hash?? Debbie Quote Link to comment https://forums.phpfreaks.com/topic/256003-how-to-safely-store-passwords/#findComment-1312770 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.