XH 1.7: Password hashing
Posted: Tue Feb 24, 2015 3:27 pm
Hello Community,
since CMSimple_XH 1.5.4 we adopted PasswordHash for hashing the admin password. For portability we opted in to the portable hashes (based on MD5). However, these hashes are relatively weak[1], and since PHP 5.3.0 (5.3.2?) PasswordHash is able to support the stronger bcrypt in a portable way. Therefore I suggest to switch to its bcrypt hashes. Note that the old passwords would be still valid (only not as safe).
An alternative might be to use PHP's native crypt(), but I don't know how to use that in a portable way. password_hash() appears to be the best option, but that is only available since PHP 5.5.0. So for now (i.e. until we require PHP 5.5) I suggest to stick with PasswordHash.
An additional benefit of PasswordHash would be the get_random_bytes() method. I'm not an expert on CSRNGs, but I'm confident that get_random_bytes() is far superior to mt_rand() or even rand() for cryptographic purposes. A presumably better alternative would be openssl_random_pseudo_bytes(), but that may not be widely available.
Anyhow, if we stick with PasswordHash, I suggest that we fully adopt it, and modify it according to our CS and use a PHP 5 constructor, add visibility specifiers and remove the fallbacks for PHP < 5. Besides the constructor, HashPassword(), CheckPassword() and get_random_bytes() (renamed to getRandomBytes()) should be public; all other methods and properties protected/private. And of course we should rename the class to XH_PasswordHash, so it can be autoloaded by the general autoloader.
I suggest to apply this patch.
Thoughts?
See also: [1] For once, it uses md5() which is not collision safe, and furthermore the stretching is implemented in PHP, which is slower. On my PC bcrypt is roughly able to use the double amount of rounds (i.e. cost+1) than the md5 based variant. Therefore we can easily switch to cost 9, and maybe we should increase that further.
since CMSimple_XH 1.5.4 we adopted PasswordHash for hashing the admin password. For portability we opted in to the portable hashes (based on MD5). However, these hashes are relatively weak[1], and since PHP 5.3.0 (5.3.2?) PasswordHash is able to support the stronger bcrypt in a portable way. Therefore I suggest to switch to its bcrypt hashes. Note that the old passwords would be still valid (only not as safe).
An alternative might be to use PHP's native crypt(), but I don't know how to use that in a portable way. password_hash() appears to be the best option, but that is only available since PHP 5.5.0. So for now (i.e. until we require PHP 5.5) I suggest to stick with PasswordHash.
An additional benefit of PasswordHash would be the get_random_bytes() method. I'm not an expert on CSRNGs, but I'm confident that get_random_bytes() is far superior to mt_rand() or even rand() for cryptographic purposes. A presumably better alternative would be openssl_random_pseudo_bytes(), but that may not be widely available.
Anyhow, if we stick with PasswordHash, I suggest that we fully adopt it, and modify it according to our CS and use a PHP 5 constructor, add visibility specifiers and remove the fallbacks for PHP < 5. Besides the constructor, HashPassword(), CheckPassword() and get_random_bytes() (renamed to getRandomBytes()) should be public; all other methods and properties protected/private. And of course we should rename the class to XH_PasswordHash, so it can be autoloaded by the general autoloader.
I suggest to apply this patch.
Thoughts?
See also: [1] For once, it uses md5() which is not collision safe, and furthermore the stretching is implemented in PHP, which is slower. On my PC bcrypt is roughly able to use the double amount of rounds (i.e. cost+1) than the md5 based variant. Therefore we can easily switch to cost 9, and maybe we should increase that further.