EchoFool Posted May 26, 2012 Share Posted May 26, 2012 Hey I have been reading about creating and storing hashes from blowfish in PHP, but am confused by the salt aspect. It says it can generate it's own ? But then surely when a user inputs their password to check against the database it will use a new salt each time and thus they won't match up when checking... say on a login screen.... this confuses me greatly.. Is it just wiser to have a fixed string of numbers to use for the salt all the time instead of letting it generate it's own ? Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/ Share on other sites More sharing options...
Oreo Posted May 26, 2012 Share Posted May 26, 2012 It says it can generate it's own ? But then surely when a user inputs their password to check against the database it will use a new salt each time and thus they won't match up when checking... say on a login screen.... this confuses me greatly.. The generated salt can be easily extracted from the string returned by blowfish, so storing that return value effectively stores both the hashed password and the salt. Consider this example: <?php $hashed = crypt('abc123'); echo $hashed . "\n"; $hashed2 = crypt('abc123'); echo $hashed2 . "\n"; $hashed3 = crypt('abc123', $hashed); echo $hashed3 . "\n"; You'll notice that the first two differ because they have different salts, however the first and the third are the same because in the third call crypt uses the salt that was generated by the first call. Is it just wiser to have a fixed string of numbers to use for the salt all the time instead of letting it generate it's own ? No, you should not (intentionally) use the same salt for multiple users. This mostly defeats the purpose of using a salt. Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/#findComment-1348732 Share on other sites More sharing options...
EchoFool Posted May 26, 2012 Author Share Posted May 26, 2012 I'm not following how your example returns the salt ? Wouldn't that just return the hash of the input + salt ? How do you get the salt out of it? Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/#findComment-1348811 Share on other sites More sharing options...
Oreo Posted May 26, 2012 Share Posted May 26, 2012 crypt() doesn't just return a hash of the input + salt, it returns a string that has a bunch of information packed into it, including, at a minimum, the algorithm type, salt and hashed value. The exact format of the string and the information it contains varies from algorithm to algorithm. For blowfish, $hashed in my example would contain four things: an identifier for the blowfish algorithm, the number of rounds run to generate the hash, the salt and finally the actual hash itself. On a similar note, the $salt parameter of crypt() isn't actually just the salt. It needs to be a specially formatted string that contains, at a minimum, the algorithm type and salt. Again, the exact format depends on the algorithm. The fact that the $salt parameter and return value of crypt are compatible formats is the reason my first example works. Another example: echo crypt('abc123', '$2a$04$saltsaltsaltsaltsaltxx'); The salt in this example is the base64 value of the string "saltsaltsaltsaltsaltxx$$" This gives you the output: $2a$04$saltsaltsaltsaltsaltxuK2.MS4sJd6ZjnuS0fp2eenjndo.g4hS You can see how the salt is embedded directly in the output, and how the salt parameter that I passed to crypt() is in the same format as the value that crypt() returned back to me. In both the $salt parameter and the return value of crypt(): $2a$ tells crypt that this is blowfish 04$ tells crypt how many rounds to use saltsaltsaltsaltsaltxx / saltsaltsaltsaltsaltxu is the salt value (more on why this differs in a moment) uK2.MS4sJd6ZjnuS0fp2eenjndo.g4hS is the hashed password One last point of potential confusion is the fact that the final "x" from the original salt appears to be missing and I've listed the "u" that replaced it as belonging to both the salt and the hash in the returned string. This is because crypt() + blowfish uses a 16 byte (128 bit) hash, but saltsaltsaltsaltsaltxx is 132 bits. The final four bits of the last 'x' are truncated, not returned by crypt() and thus not present in the returned version of the hash. For this reason, using "saltsaltsaltsaltsaltxy" as your salt will give you exactly the same output as using "saltsaltsaltsaltsaltxx", but using "saltsaltsaltsaltsaltxA" will give you a different value. It is possible to extract the first 16 bytes of the original salt from the value returned by crypt(), but this is not something you'll probably ever need to do unless you happen to be writing your own implementation of crypt. Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/#findComment-1348820 Share on other sites More sharing options...
EchoFool Posted May 26, 2012 Author Share Posted May 26, 2012 So something like this? <?php $result = crypt('abc123', '$2a$04$saltsaltsaltsaltsaltxx'); $array = explode('.',$result); $salt = $array[0]; $hash_pss = $array[1].$array[2]; ?> Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/#findComment-1348826 Share on other sites More sharing options...
EchoFool Posted May 26, 2012 Author Share Posted May 26, 2012 Also i didn't get the same output as you ... i got: echo crypt('abc123', '$2a$04$saltsaltsaltsaltsaltxx'); Result : $2pGiQ0v1IyNY Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/#findComment-1348840 Share on other sites More sharing options...
Oreo Posted May 27, 2012 Share Posted May 27, 2012 So something like this? No, the dot is not a separator character. The salt and the hashed password are concatenated together and then base64 encoded. A dot happens to be one of the characters used for base64 encoding, so it could show up anywhere in the string. The only way to separate them is to first extract the salt+hash encoded string from the value returned by hash, which always follows the third $, then base64 decode that, and then extract the first 16 bytes as the salt and the remainder as the hash. At that point you will have two strings of raw binary values which will not render well as ASCII, you would have to base64 encode them again to display them as ASCII. The primary complication with this is that crypt() uses a different base64 encoding alphabet than PHP's base64_encode and base64_decode functions, so you cannot use them for that part of the process. Also i didn't get the same output as you ... i got: Your system is not using blowfish for some reason and is instead falling back on what looks like standard DES. Quote Link to comment https://forums.phpfreaks.com/topic/263157-blowfish-with-salt-security/#findComment-1348960 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.