Richard_Grant Posted September 8, 2014 Share Posted September 8, 2014 (edited) I have been out of the game for a while and i need a bit of guidance on this. Password: HelloWorld! Salt: mySaltForMyReallyCoolPasswordThatiMadeForPHPFREAKS MD5 . SALT = 072ce1d7fd7e6f14ba12053a9e057b26 SHA1 . SALT = d580f4880e29ed757d942623f4d96dab1976d929 Crypt . SALT = my7LFLALq6s3c password_hash = $2y$13$mySaltForMyReallyCoolO9t3RUqt1WbzVeqqQGxDHqOF/nu2Zhs2 Which security protocol is most prefered. SALT . MD5 . SALT http://php.net/manual/en/function.md5.php SHA1 . SALT http://php.net/manual/en/function.sha1.php Crypt http://php.net/manual/en/function.crypt.php password_hash http://php.net/manual/en/function.password-hash.php (new) function: <?PHP $password = "HelloWorld!"; $salt = "mySaltForMyReallyCoolPasswordThatiMadeForPHPFREAKS"; $md5 = md5($password . $salt); $sha1 = $sha1($password . $salt); $crypt = crypt($password, $salt); $o = [ 'cost' => 13, 'salt' => $salt, ]; $password_hash = password_hash($p, PASSWORD_DEFAULT, $o); ?> After i get the encrypted password, i will convert it to binary and then store it in the database as a binary. Which of these methods do you prefer and why? (ps. i might have used password_hash incorrectly). i don't need any source code, just fill me in Edited September 8, 2014 by Richard_Grant Quote Link to comment Share on other sites More sharing options...
Strider64 Posted September 8, 2014 Share Posted September 8, 2014 (edited) Don't re-invent the wheel, use a proven secure php password library - https://github.com/ircmaxell/password_compat Edited September 8, 2014 by Strider64 Quote Link to comment Share on other sites More sharing options...
Solution kicken Posted September 8, 2014 Solution Share Posted September 8, 2014 Use the password_hash function. Specify PASSWORD_BCRYPT rather than the default and do NOT specify a salt, let PHP generate it for you. You should specify a cost however. password_hash($password, PASSWORD_BCRYPT, array('cost' => 14)); You'll want to play with the cost value until the function takes about a second to complete. You can measure the time using microtime, such as: <?php $s = microtime(true); password_hash('abcdefg', PASSWORD_BCRYPT, array('cost'=>14)); $e = microtime(true); var_dump($e-$s); When storing the hash to the database there is no reason to convert it into some kind of binary representation, whatever you mean by that. Just store the string into a VARCHAR column. As for the why, MD5 has collision weaknesses, and both it and SHA are fast algorithms which is NOT a good thing for password hashing. For password hashing you want an algorithm that is slow and/or memory intensive so that someone who is trying to brute-force the hashes is forced to spend a lot of time on it and/or expend significant resources. bcrypt is designed for password hashing and is slow and expensive. It does however have it's own limitations that you should be aware of. 1 Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 8, 2014 Share Posted September 8, 2014 First of all, this is hashing, not encryption. Those are two entirely different concepts, and it's very important to not confuse them. General-purpose hash algorithms like MD5, SHA-1, SHA-2 etc. are inacceptable for password hashing. They're designed for an entirely different purpose (like data integrity), and they're supposed to be very fast. When dealing with passwords, this property makes them extremely vulnerable to brute force attacks. For example, an old gamer GPU can calculate billions(!) of MD5 or SHA hashes per second. If the attacker is willing to pay some extra money for specialized hardware or a cloud computing service, they can have trillions of hashes per second. It's easy to see that even strong passwords won't survive such an attack. This home-made salting scheme also doesn't help at all. In fact, you should never invent your own security algorithms. Leave that to the experts. The crypt() function can theoretically be used to hash passwords. However, there are two big problems: Most algorithms it offers are long obsolete. Most people have no idea how to use it correctly (and appearently don't bother to read the manual). Unfortunately, this applies to you as well: When you just pass some gibberish to the second parameter, you get the extremely weak DES-based algorithm. Even worse, this algorithm only processes the first 8 bytes/characters of the password and ignores the rest. So crypt() is out of question as well. That leaves you with password_hash(), and this is indeed the best solution. It uses very strong algorithms (currently bcrypt), and it's specifically designed for non-experts. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 8, 2014 Share Posted September 8, 2014 As for the why, MD5 has collision weaknesses No, no, no. Please stop spreading this nonsense. Collision resistance has absolutely nothing to do with password hashing, and I have no idea why this myth keeps popping up in discussions. A collision attack means finding two arbitrary preimages which map to the same hash. That doesn't help us find passwords at all. What we need is a preimage which maps to a particular hash. And that's an antirely different scenario aptly called preimage attack. This may seem like an unimportant detail, but many people actually believe this collision stuff and choose the algorithm based on collision resistance (e. g. SHA-2). That's a huge mistake, because SHA-2 is just as unsuitable for password hashing as MD5. The problem of MD5 is its efficiency, not its issues with collisions. In fact, you may very well use MD5 for high-entropy input like random tokens. Quote Link to comment Share on other sites More sharing options...
Psycho Posted September 8, 2014 Share Posted September 8, 2014 A collision attack means finding two arbitrary preimages which map to the same hash. That doesn't help us find passwords at all. What we need is a preimage which maps to a particular hash. And that's an antirely different scenario aptly called preimage attack. To elaborate: MD5 hashes are commonly used as a checksum on files so you can verify the file you just downloaded has not been tampered with from what the original provider intended (e.g. someone has inserted a virus). It is in this context that collisions become an issue. With a large source it is possible to create another file with the same size which would produce the same hash - defeating the purpose of a checksum. With the "relatively" limited number of possible password combinations that could be produced with 8-40ish of the available characters, I would guess it is a safe bet that no collisions would exist in that range. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 8, 2014 Share Posted September 8, 2014 I think you're still confusing collision attacks and preimage attacks. To find a password, you need a preimage for a particular hash. It doesn't help you that somewhere there are two preimages which both map to some other hash. You need this hash. And that's is a preimage attack, not a collision attack. Or maybe you think that collisions are so common that an attacker can choose from a large pool of different strings which are all accepted as a valid password? No. Collisions don't just happen by accident, you need to actually find them. So again: Collision resistance is not relevant for password hashing. This claim is just wrong and leads to the wrong conclusions. You do need collisions resistance for things like digital signatures, but that's an entirely different topic. Right now, we're talking about passwords. Quote Link to comment Share on other sites More sharing options...
Richard_Grant Posted September 8, 2014 Author Share Posted September 8, 2014 (edited) Use the password_hash function. Specify PASSWORD_BCRYPT rather than the default and do NOT specify a salt, let PHP generate it for you. You should specify a cost however. password_hash($password, PASSWORD_BCRYPT, array('cost' => 14)); You'll want to play with the cost value until the function takes about a second to complete. You can measure the time using microtime, such as: <?php $s = microtime(true); password_hash('abcdefg', PASSWORD_BCRYPT, array('cost'=>14)); $e = microtime(true); var_dump($e-$s); When storing the hash to the database there is no reason to convert it into some kind of binary representation, whatever you mean by that. Just store the string into a VARCHAR column. As for the why, MD5 has collision weaknesses, and both it and SHA are fast algorithms which is NOT a good thing for password hashing. For password hashing you want an algorithm that is slow and/or memory intensive so that someone who is trying to brute-force the hashes is forced to spend a lot of time on it and/or expend significant resources. bcrypt is designed for password hashing and is slow and expensive. It does however have it's own limitations that you should be aware of. Okay so i just learned how to use passowrd correctly: $password = "HelloWorld!"; $options = [ 'cost' => 14 ]; $hash = password_hash($password, PASSWORD_BCRYPT, $options); echo $hash . "<br>"; if(password_verify($password, $hash)){ echo "Match"; } I was unaware of the password_verify function, which is why i chose to use PASSWORD_DEFAULT but i opened up the manual . Which brings me to my next point... If password_verify checks if $password & $hash are equal, doesn't that mean that $hash is being (de-hashed)? Edited September 8, 2014 by Richard_Grant Quote Link to comment Share on other sites More sharing options...
jcbones Posted September 9, 2014 Share Posted September 9, 2014 No it doesn't. In fact, this is explained in the manual. The used algorithm, cost and salt are returned as part of the hash. Therefore, all information that's needed to verify the hash is included in it. This allows the password_verify() function to verify the hash without needing separate storage for the salt or algorithm information. 1 Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 9, 2014 Share Posted September 9, 2014 (edited) If password_verify checks if $password & $hash are equal, doesn't that mean that $hash is being (de-hashed)? No. There's no such thing as “de-hashing”. The whole point of hash algorithms is that they cannot be reverted. The result of password_hash() contains all parameters of the original hash calculation: the algorithm (“2y” means bcrypt), the cost factor (in my case 10) and the salt (128 bits), followed by actual hash (184 bits). -------------------------------------------------------------------------------------------------------- $2y$10$4DD6Ts9Lw4gZOKoYCd3iferiRKfNGHuMIMgbBkRSHQyal0NqHvBKK -------------------------------------------------------------------------------------------------------- To verify a password, the function hashes it with the exact same parameters and then compares the result with the given hash. If the hashes match, then the password is correct, otherwise it's wrong. It's the same thing you did with MD5: To verify a password, you hash it and then compare the result with the MD5 hash in your database. If they match, then the password is correct. Edited September 9, 2014 by Jacques1 Quote Link to comment Share on other sites More sharing options...
Richard_Grant Posted September 9, 2014 Author Share Posted September 9, 2014 (edited) No it doesn't. In fact, this is explained in the manual. Thank you @jcbones that was EXTREMELY helpful. So here is the function i will be using for password hashing: (tell me what you would do differently if anything) <?php class password_handle{ public static function hashbinary($password){//converts string to binary $hash = password_hash($password, PASSWORD_BCRYPT, array('cost'=>14)); $bin_layer = ""; $hash_split = str_split($hash); for($i = 0; $i < count($hash_split);$i++){ $bin = decbin(ord($hash_split[$i])); $bin_l = strlen($bin); if($bin_l < 7){ $pad =""; for($j =0; $j < 7 - $bin_l;$j++){ $pad .= "0"; } $bin = $pad . $bin; } $char = chr(bindec($bin)); $bin_layer .= $bin; } return $bin_layer; } public static function verifyhash($password, $bin_password){//verifies that the hash is equal to the password return (password_verify($password, self::binarystring($bin_password))) ? true : false; } private function binarystring($binary){//converts binary to string $char_layer = ""; $bin_split = str_split($binary, 7); for($i = 0; $i < count($bin_split); $i++){ $char_layer .= chr(bindec($bin_split[$i])); } return $char_layer; } } $password = "HelloWorld!"; $p_h = new password_handle(); $hashbin = $p_h::hashbinary($password); //Store this in database /* 01001000110010111100101001000110001011010001001000110111111011101101001101000011100011001011000010 11110001011001011100001011101000101101010110110101010000111011011001101001011111101011101101110110 10011111101010100110110010111101101101100101011101001101111101010101011101001101000011001101011010 11100010110001110011011010101010001011001010101111000010111010011110101001111100001010000101110000 110011010010111001010010111 */ if($p_h::verifyhash($password,$hashbin)){//if password is the same as the hash echo "true"; }else{ echo "false"; } ?> What is happening there is: i password_hash the string with PASSWORD_BCRYPT allowing they method to determine its own salt I convert the hash to a binary string for storing in my mysql database I check if the binary hash is equal to the password string. Edited September 9, 2014 by Richard_Grant Quote Link to comment Share on other sites More sharing options...
jazzman1 Posted September 9, 2014 Share Posted September 9, 2014 i password_hash the string with PASSWORD_BCRYPT allowing they method to determine its own salt I convert the hash to a binary string for storing in my mysql database I check if the binary hash is equal to the password string. And the question is why? This is a horrible and sadistic thing against you computer and all services on it Quote Link to comment Share on other sites More sharing options...
jazzman1 Posted September 9, 2014 Share Posted September 9, 2014 To elaborate: MD5 hashes are commonly used as a checksum on files so you can verify the file..... Psycho, have you read the bugs message from authors of this program? The MD5 algorithm should not be used any more for security related pur‐ poses. Instead, better use an SHA-2 algorithm, implemented in the pro‐ grams sha224sum(1), sha256sum(1), sha384sum(1), sha512sum(1) Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 9, 2014 Share Posted September 9, 2014 So here is the function i will be using for password hashing: (tell me what you would do differently if anything) What in God's name are you doing there? Seriously, what the fuck is this? Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 9, 2014 Share Posted September 9, 2014 Note that this is not a “binary string”. It's literally a sequence of the characters “0” and “1”, which means this takes 8 times as much space. It's entirely unclear why you would do this. There also seems to be some confusion regarding the number of bits in a byte. One byte is 8 bits (not 7). Just store the hash in a CHAR(60) column. It's generally a good idea to get the basic code done before you start implementing strange ideas. Quote Link to comment Share on other sites More sharing options...
Richard_Grant Posted September 9, 2014 Author Share Posted September 9, 2014 Note that this is not a “binary string”. It's literally a sequence of the characters “0” and “1”, which means this takes 8 times as much space. It's entirely unclear why you would do this. There also seems to be some confusion regarding the number of bits in a byte. One byte is 8 bits (not 7). Just store the hash in a CHAR(60) column. It's generally a good idea to get the basic code done before you start implementing strange ideas. I'm not going to lie, i wasn't thinking about bytes when i wrote that. (i will update that now). In my case speed is not an issue, i am sacrificing speed for security. TBH i haven't decided if i want to store the binary string as a BINARY in the database or convert the binary string to byte array and add it to the database as a BLOB, Quote Link to comment Share on other sites More sharing options...
Psycho Posted September 9, 2014 Share Posted September 9, 2014 I think you're still confusing collision attacks and preimage attacks. To find a password, you need a preimage for a particular hash. It doesn't help you that somewhere there are two preimages which both map to some other hash. You need this hash. And that's is a preimage attack, not a collision attack. Or maybe you think that collisions are so common that an attacker can choose from a large pool of different strings which are all accepted as a valid password? No. Collisions don't just happen by accident, you need to actually find them. So again: Collision resistance is not relevant for password hashing. This claim is just wrong and leads to the wrong conclusions. You do need collisions resistance for things like digital signatures, but that's an entirely different topic. Right now, we're talking about passwords. Was that in response to my post? I was agreeing with you. Perhaps it is you that is confused. I specifically stated that collisions were a non-issue with respect to passwords. The collisions are only an issue when using a hash for something such as a checksum where an alternative file could be created to appear to be the target file with potential malicious modifications, and yet produce the same hash. It is not an easy thing to do, but it is possible. Again, I was just elaborating on your previous comment. Quote Link to comment Share on other sites More sharing options...
Richard_Grant Posted September 9, 2014 Author Share Posted September 9, 2014 Was that in response to my post? I was agreeing with you. Perhaps it is you that is confused. I specifically stated that collisions were a non-issue with respect to passwords. The collisions are only an issue when using a hash for something such as a checksum where an alternative file could be created to appear to be the target file with potential malicious modifications, and yet produce the same hash. It is not an easy thing to do, but it is possible. Again, I was just elaborating on your previous comment. Psycho, whats your opinion about storing a hashed password as a binary in a mysql database? Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted September 9, 2014 Share Posted September 9, 2014 In my case speed is not an issue, i am sacrificing speed for security. What? How are those weird digit sequences supposed to increase security? It's the exact opposite: I wouldn't be surprised if there's a bug somewhere. TBH i haven't decided if i want to store the binary string as a BINARY in the database or convert the binary string to byte array and add it to the database as a BLOB, Please don't. I think you've put a lot of strange ideas into your head, and now it's time to get back to reality. Store the result of password_hash() in a CHAR(60) column like everybody else on this planet. I understand that you're into math and like to play around with different bases. But user passwords aren't the right thing to play with. Make this a separate project. Was that in response to my post? I was agreeing with you. Perhaps it is you that is confused. I am referring to your last sentence where you stated that there are probably no collision in the space of typical passwords. Now, maybe you just meant that as a kind of “fun fact” with no relation to the previous text. But I read it as: The reason why collision attacks are not a problem for passwords is because there are no collision in that space. And that would be plain wrong. Quote Link to comment Share on other sites More sharing options...
Psycho Posted September 9, 2014 Share Posted September 9, 2014 I am referring to your last sentence where you stated that there are probably no collision in the space of typical passwords. Now, maybe you just meant that as a kind of “fun fact” with no relation to the previous text. But I read it as: The reason why collision attacks are not a problem for passwords is because there are no collision in that space. And that would be plain wrong. I see what you mean. I could have been more clear. What I was trying to state was that the possibility of collisions within that space of permutations is so infinitesimally remote that the discussion of whether they are an issue or not for passwords is not even worth discussing. And, trying to even use collisions for the purpose of cracking a password would be a foolish endeavor. Psycho, whats your opinion about storing a hashed password as a binary in a mysql database? I don't see the point. Are you thinking that storing it in this way will trip up someone trying to brute force the values? I guess that is a possibility, but think about "who" you are trying to protect the data from. This would be people with decent technical skills. Assuming you are already using a good hashing method, these would be people that have enough knowledge to reverse engineer the hashing method to create the logic to run a brute force attack. Do really think this type of person would not recognize that the hash is stored in binary and just add that to the brute-force process? I would run off the assumption that a person who has infiltrated my DB has likely accessed the source files as well. And, in that case they can "see" that the values are stored in binary. All this does is add a small level of obfuscation. And, obfuscation does not equal increased security in my opinion. Quote Link to comment 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.