moose-en-a-gant Posted January 8, 2015 Share Posted January 8, 2015 (edited) I don't know if my password encrytion has been done correctly / is actually secure. I don't have anything valuable at the moment that people would care to hack, but in the future I want to be absolutely certain I am doing it right. This is my process, I am storing it as Varchar(255), did a cost test and 9 was my result $hash = password_hash($passsword, PASSWORD_BCRYPT, array("cost"=>9)); I was told I don't need a salt since it is included in the password_hash function Also I noticed most of the hashes if not all start like this, why is that? $2y$09$ Thanks for any help Edited January 8, 2015 by moose-en-a-gant Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/ Share on other sites More sharing options...
requinix Posted January 8, 2015 Share Posted January 8, 2015 You shouldn't specify the hashing algorithm. password_hash() will use the best one available by default, and if that changes from bcrypt in the future you'll want to make sure you're using it. The hashes are backwards-compatible so you don't have to worry about a hash not working in the future. The $2y$ is how PHP recognizes that the bcrypt algorithm was used to generate the hash. Check the documentation on crypt to see what salts look like: you'll see that the bcrypt ("b" stands for blowfish) salt is formatted as "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z".The password "hash" itself is a valid salt, since it was constructed to be salt + raw password hash. To verify a password, password_verify() salts the password using the hash and makes sure the new hash matches the old one. It is as simple as crypt($password, $password_hash) == $password_hash Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/#findComment-1502191 Share on other sites More sharing options...
Jacques1 Posted January 9, 2015 Share Posted January 9, 2015 You should specifiy the hash algorithm and cost (like you already did). Do not rely on the default settings. The whole point of modern password hashing is that you tune the settings for your specific hardware and requirements. You seem to have done that already, and that's great. However, you should store the parameters in a configuration file and automatically update the hashes when the settings change. This way you can easily keep the parameters up-to-date: <?php // put the hash parameters into a configuration file so that you can easily change them define('APP_PASSWORD_HASH_ALGORITHM', PASSWORD_BCRYPT); define('APP_PASSWORD_HASH_COST', 9); // hashing a password (e. g. during registration) $password_hash = password_hash($password, APP_PASSWORD_HASH_ALGORITHM, array('cost' => APP_PASSWORD_HASH_COST)); // verifying a password; if the parameters are out-of-date, the hash is automatically updated if (password_verify($password, $stored_hash)) { # do the log-in procedure // need a hash update? if (password_needs_rehash($stored_hash, APP_PASSWORD_HASH_ALGORITHM, array('cost' => APP_PASSWORD_HASH_COST))) { $new_password_hash = password_hash($password, APP_PASSWORD_HASH_ALGORITHM, array('cost' => APP_PASSWORD_HASH_COST)); # do the UPDATE query } } else { # password incorrect } Note that bcrypt hashes are always 60 ASCII characters long, so a CHAR(60) is sufficient. Also note that bcrypt can only process up to 56 bytes of input, so you need to validate the user-provided password and warn them if it's too long: <?php // put this into a configuration file define('APP_MIN_PASSWORD_LENGTH', 6); define('APP_MAX_PASSWORD_LENGTH', 56); // bcrypt can only process up to 56 bytes of input if (mb_strlen($password, '8bit') < APP_MIN_PASSWORD_LENGTH) { # too short } elseif (mb_strlen($password, '8bit') > APP_MAX_PASSWORD_LENGTH) { # too long } else { # length OK } Without this check, the password may be silently truncated (if it exceeds 72 bytes), and that obviously should never happen. Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/#findComment-1502231 Share on other sites More sharing options...
Strider64 Posted January 9, 2015 Share Posted January 9, 2015 @Jacques1 I agree about checking the password's length, but I can't imagine a person in their right mind wanted a password that long. Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/#findComment-1502266 Share on other sites More sharing options...
moose-en-a-gant Posted January 9, 2015 Author Share Posted January 9, 2015 You shouldn't specify the hashing algorithm. Did I? What I posted above is what I use. I use password verify, I use this: if (password_verify($passsword, $hash_from_db)) { $_SESSION["user"]=$userrname; function Redirect($url, $permanent = false) { { if (headers_sent() === false) { header('Location: ' . $url, true, ($permanent === true) ? 301 : 302); } exit(); } Redirect(' userpanel ', false); } So if I use that for verification, and this for hashing, am I safe? $hash = password_hash($passsword, PASSWORD_BCRYPT, array("cost" => 9)); Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/#findComment-1502301 Share on other sites More sharing options...
moose-en-a-gant Posted January 9, 2015 Author Share Posted January 9, 2015 (edited) You should specifiy the hash algorithm and cost (like you already did). Do not rely on the default settings. The whole point of modern password hashing is that you tune the settings for your specific hardware and requirements. You seem to have done that already, and that's great. However, you should store the parameters in a configuration file and automatically update the hashes when the settings change. This way you can easily keep the parameters up-to-date: <?php // put the hash parameters into a configuration file so that you can easily change them define('APP_PASSWORD_HASH_ALGORITHM', PASSWORD_BCRYPT); define('APP_PASSWORD_HASH_COST', 9); // hashing a password (e. g. during registration) $password_hash = password_hash($password, APP_PASSWORD_HASH_ALGORITHM, array('cost' => APP_PASSWORD_HASH_COST)); // verifying a password; if the parameters are out-of-date, the hash is automatically updated if (password_verify($password, $stored_hash)) { # do the log-in procedure // need a hash update? if (password_needs_rehash($stored_hash, APP_PASSWORD_HASH_ALGORITHM, array('cost' => APP_PASSWORD_HASH_COST))) { $new_password_hash = password_hash($password, APP_PASSWORD_HASH_ALGORITHM, array('cost' => APP_PASSWORD_HASH_COST)); # do the UPDATE query } } else { # password incorrect } Note that bcrypt hashes are always 60 ASCII characters long, so a CHAR(60) is sufficient. Also note that bcrypt can only process up to 56 bytes of input, so you need to validate the user-provided password and warn them if it's too long: <?php // put this into a configuration file define('APP_MIN_PASSWORD_LENGTH', 6); define('APP_MAX_PASSWORD_LENGTH', 56); // bcrypt can only process up to 56 bytes of input if (mb_strlen($password, '8bit') < APP_MIN_PASSWORD_LENGTH) { # too short } elseif (mb_strlen($password, '8bit') > APP_MAX_PASSWORD_LENGTH) { # too long } else { # length OK } Without this check, the password may be silently truncated (if it exceeds 72 bytes), and that obviously should never happen. Oh man this is great thank you, I like that password length check, I was concerned about using varchar(255), I mean I had read about 2*128 or something so 256 I figured was the standard for storing when using SHA255 or something. I think that it is unused space then. Specifying a larger length isn't a waste is it? Is that allocating spare space that is "taken" by empty spaces? When you say configuration file, do you mean a stand alone php file that I include at the top of a registration page / login page? Edited January 9, 2015 by moose-en-a-gant Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/#findComment-1502302 Share on other sites More sharing options...
Jacques1 Posted January 9, 2015 Share Posted January 9, 2015 A VARCHAR(n) doesn't allocate space for the unused characters. It does allocate one or two extra bytes to store the length, but that's of course irrelevant. However, the problem of your VARCHAR(255) is that you lose type safety: MySQL will accept any string up to 255 characters, so if there's a bug in your application, you may end up storing tons of invalid hashes and not realize it. This cannot happen with a proper CHAR(60), because in that case, MySQL will actually warn you or even reject the data (in strict mode) if the input string is too long. So I strongly recommend that you always use the correct size. This is also important for us, the programmers, because an explicit length tells us immediately what the application expects. When you say configuration file, do you mean a stand alone php file that I include at the top of a registration page / login page? Yes, something like that. Of course it doesn't have to be a PHP file, it might as well be XML, JSON, INI or whatever format you prefer. If you already have a configuration mechanism, simply add the hash parameters. Quote Link to comment https://forums.phpfreaks.com/topic/293761-how-do-you-know-if-your-password-encryption-security-is-correctly-implemented/#findComment-1502311 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.