sKunKbad Posted December 13, 2015 Share Posted December 13, 2015 I've been using PHP's crypt function to hash passwords, and specifically using the CRYPT_BLOWFISH hash type. I see where it is the salt, delimited by dollar signs that tells PHP how to hash the password. $2y$ at the beginning of the salt says to use CRYPT_BLOWFISH, unless on an older version of PHP, and then it's $2a$ or $2x$. The cost parameter comes next, and setting that is easy, just a number between 04 and 31. Next the docs say to have a string that is 22 characters, from the alphabet "./0-9A-Za-z". It does mention that characters outside this range will cause crypt to return a zero length string. What it doesn't say is if more than 22 characters can be supplied. It also doesn't mention if the dollar sign at the end is mandatory. Oddly enough, the example that the PHP docs gives has more than 22 characters (26): if (CRYPT_BLOWFISH == 1) { // usesomesillystringforsalt is actually 26 characters echo 'Blowfish: ' . crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$') . "\n"; } So, what is the deal here? Can I supply 32, 64, etc.? Is it just truncated by PHP? It isn't returning a zero length string when I use 32. Quote Link to comment Share on other sites More sharing options...
benanamen Posted December 13, 2015 Share Posted December 13, 2015 Is there some reason you are not using the password_hash function? Quote Link to comment Share on other sites More sharing options...
sKunKbad Posted December 13, 2015 Author Share Posted December 13, 2015 Is there some reason you are not using the password_hash function? The server requirements for this application allow for PHP 5.3+. Also, password_hash is just a wrapper for crypt, so this shouldn't be an issue. Quote Link to comment Share on other sites More sharing options...
Solution Jacques1 Posted December 14, 2015 Solution Share Posted December 14, 2015 Trust me, it's not “just a wrapper”. Even the original author of the password API got it wrong a couple of times, because the crypt() function is weird as hell and had several bugs in different PHP versions. Unless you've actually inspected the C source code, read through the bugtracker and fully understand how bcrypt works, it's just dangerous to use crypt() directly. The salt is not an arbitrary string, and the manual is very misleading. What the crypt() function actually expects is a sequence of 128 random bits generated with a CSPRNG and encoded with a special Base64 variant (not the usual Base64). If you fail to provide a valid salt, pretty much anything can happen. And that was the easy part. How do you get a proper CSPRNG accross all PHP versions and operating systems? Are you aware of the bcrypt input limitations (no more than 56 bytes, no null bytes)? How do you enforce that? Note that strlen() may either return the number of bytes or the number of characters, depending on whether it has been overloaded by the Mcrypt extension. Are you aware of the various error representation and output bugs? How do you validate the resulting hash? How do you prevent timing attacks when you compare the calculated hash with the expected hash? ... I strongly recommend you use a library which has already gone through this like password_compat. 3 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.