Dexlin Posted June 8, 2011 Share Posted June 8, 2011 Hi everyone, I understand the idea behind salting hashes to make things more secure even though nothing is 100% secure anyway, but as salting uses a string of numbers, letters upper and lower case etc which is always different then gets added onto the start,end or in the middle of the hash to make the key different. Where this is the case how can this be authenticated as the salt is always different and you will need up with not being able to login as the salt makes the hash either sha1/2 md5 in question always different. If you understand what im saying. Many thanks Quote Link to comment https://forums.phpfreaks.com/topic/238793-question-about-authenticating-with-salted-hash/ Share on other sites More sharing options...
xyph Posted June 8, 2011 Share Posted June 8, 2011 You have to store the salt along with the hash in a known way, so you can extract it yourself later. You have to do a query like SELECT `user`, `pass`, `access_level` FROM `users` WHERE `user` = $_POST['username']; If that query fails, you know they're misspelled their username or it doesn't exist. Otherwise, you extract the salt from the password hash you just looked up and compare. Here's the way I deal with random salted passwords. It's pretty damn secure, and even with known pass->hash combos it's really difficult to reverse and brute. <?php // Unique key - I use this to add further entropy between sripts, or multiple // implementations within a script. It will further be used in hash_hmac, which // forces an attacker to use a custom rainbow table for your site EVEN IF they // manage to extract the salts, and learn how the salt is mixed in pre-hash $key = 'ANY RANDOM STUFF CAN GO HERE. CAN BE LONG, CAN BE SHORT. I LIKE AT LEAST 20 CHARS'; // I plan on splitting the salt in half, and storing it in variable spots within // the hash. This will tell us where the second split happens $split = 6; $password = 'FOOBAR'; $hash = make_hash( $password, $key, $split ); // The cool thing here is EVERY time you refresh the page you'll end up with a VERY // different hash. If two users enter the same password, the chances of the hash being // the same is miniscule. echo "The hash of $password is $hash<br />"; if ( compare_hash($password, $hash, $key, $split ) ) echo "Passwords match on comparison"; else echo "Something went wrong!"; function make_hash( $pass, $key, $split ) { $passLength = strlen( $pass ); // Get the length of the password // If the password is really long, we dont want to push the salt // to the far end of the hash. while ( $passLength > 30 ) $passLength -= 30; $salt = uuid(); $hash = hash_hmac( 'sha256', $salt.$pass, $key ); // Mix in the salt with the hash return substr($hash,0,$passLength).substr($salt,0,$passLength). substr($hash,$passLength,$split).substr($salt,$passLength). substr($hash,$passLength+$split-1); // Returns FirstPartHash.FirstPartSalt.SecondPartHash.LastPartSalt.LastPartHash // The salt is mixed into the hash based on the password length, making it VERY // hard to reverse. } function compare_hash( $pass, $compare, $key, $split ) { $passLength = strlen( $pass ); while ( $passLength > 30 ) $passLength -= 30; // Extract the salt from the $compare hash. $salt = substr($compare,$passLength,$passLength).substr($compare,$passLength*2+$split,32-$passLength); // Once we have the salt, build the hash and see if it compares. $hash = hash_hmac( 'sha256', $salt.$pass, $key ); $hash = substr($hash,0,$passLength).substr($salt,0,$passLength). substr($hash,$passLength,$split).substr($salt,$passLength). substr($hash,$passLength+$split-1); if( $hash === $compare ) return TRUE; else return FALSE; } // RFC4122 UUID Generator v4 - I prefer this over uniqid() due to a constant 128bit // output, and no use of the time function. It's pseudo-unique, but will work very // well for our application. function uuid( ) { return sprintf( '%04x%04x%04x%04x%04x%04x%04x%04x', mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0x0fff ) | 0x4000, mt_rand( 0, 0x3fff ) | 0x8000, mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) ); } ?> Quote Link to comment https://forums.phpfreaks.com/topic/238793-question-about-authenticating-with-salted-hash/#findComment-1227027 Share on other sites More sharing options...
PFMaBiSmAd Posted June 8, 2011 Share Posted June 8, 2011 If you are asking about a random salt, you would store that random salt with the resulting hash value (some of the hash functions actually produce a fixed length random salt and prepend it to the beginning of the hashed value that they produce.) Quote Link to comment https://forums.phpfreaks.com/topic/238793-question-about-authenticating-with-salted-hash/#findComment-1227029 Share on other sites More sharing options...
Dexlin Posted June 8, 2011 Author Share Posted June 8, 2011 Thanks for that ill have a look at your code to see if i can understnad it , i thought there was a answer for it but i couldn't think what it was Thanks again You have to store the salt along with the hash in a known way, so you can extract it yourself later. You have to do a query like SELECT `user`, `pass`, `access_level` FROM `users` WHERE `user` = $_POST['username']; If that query fails, you know they're misspelled their username or it doesn't exist. Otherwise, you extract the salt from the password hash you just looked up and compare. Here's the way I deal with random salted passwords. It's pretty damn secure, and even with known pass->hash combos it's really difficult to reverse and brute. <?php // Unique key - I use this to add further entropy between sripts, or multiple // implementations within a script. It will further be used in hash_hmac, which // forces an attacker to use a custom rainbow table for your site EVEN IF they // manage to extract the salts, and learn how the salt is mixed in pre-hash $key = 'ANY RANDOM STUFF CAN GO HERE. CAN BE LONG, CAN BE SHORT. I LIKE AT LEAST 20 CHARS'; // I plan on splitting the salt in half, and storing it in variable spots within // the hash. This will tell us where the second split happens $split = 6; $password = 'FOOBAR'; $hash = make_hash( $password, $key, $split ); // The cool thing here is EVERY time you refresh the page you'll end up with a VERY // different hash. If two users enter the same password, the chances of the hash being // the same is miniscule. echo "The hash of $password is $hash<br />"; if ( compare_hash($password, $hash, $key, $split ) ) echo "Passwords match on comparison"; else echo "Something went wrong!"; function make_hash( $pass, $key, $split ) { $passLength = strlen( $pass ); // Get the length of the password // If the password is really long, we dont want to push the salt // to the far end of the hash. while ( $passLength > 30 ) $passLength -= 30; $salt = uuid(); $hash = hash_hmac( 'sha256', $salt.$pass, $key ); // Mix in the salt with the hash return substr($hash,0,$passLength).substr($salt,0,$passLength). substr($hash,$passLength,$split).substr($salt,$passLength). substr($hash,$passLength+$split-1); // Returns FirstPartHash.FirstPartSalt.SecondPartHash.LastPartSalt.LastPartHash // The salt is mixed into the hash based on the password length, making it VERY // hard to reverse. } function compare_hash( $pass, $compare, $key, $split ) { $passLength = strlen( $pass ); while ( $passLength > 30 ) $passLength -= 30; // Extract the salt from the $compare hash. $salt = substr($compare,$passLength,$passLength).substr($compare,$passLength*2+$split,32-$passLength); // Once we have the salt, build the hash and see if it compares. $hash = hash_hmac( 'sha256', $salt.$pass, $key ); $hash = substr($hash,0,$passLength).substr($salt,0,$passLength). substr($hash,$passLength,$split).substr($salt,$passLength). substr($hash,$passLength+$split-1); if( $hash === $compare ) return TRUE; else return FALSE; } // RFC4122 UUID Generator v4 - I prefer this over uniqid() due to a constant 128bit // output, and no use of the time function. It's pseudo-unique, but will work very // well for our application. function uuid( ) { return sprintf( '%04x%04x%04x%04x%04x%04x%04x%04x', mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0x0fff ) | 0x4000, mt_rand( 0, 0x3fff ) | 0x8000, mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) ); } ?> Quote Link to comment https://forums.phpfreaks.com/topic/238793-question-about-authenticating-with-salted-hash/#findComment-1227054 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.