Я хочу хранить защищенные пароли пользователей в базе данных MySQL с помощью PHP.
Как я могу сделать это лучше?
Мои занятия:
private static $algo = '$2a'; private static $cost = '$10'; private static $pepper = 'eMI8MHpEByw/M4c9o7sN3d'; public static function generateSalt($length) { $randomBinaryString = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); $randomEncodedString = str_replace('+', '.', base64_encode($randomBinaryString)); return substr($randomEncodedString, 0, $length); } public static function generateHash($password) { if (!defined('CRYPT_BLOWFISH')) die('The CRYPT_BLOWFISH algorithm is required (PHP 5.3).'); $password = hash_hmac('sha256', $password, self::$pepper, false); return crypt($password, self::$algo . self::$cost . '$' . self::generateSalt(22)); } public static function checkPassword($hash, $password) { $salt = substr($hash, 0, 29); $password = hash_hmac('sha256', $password, self::$pepper, false); $new_hash = crypt($password, $salt); return ($hash == $new_hash); }
Используйте либо предложения этого ответа (для PHP> = 5.5), либо следующий класс. Благодаря martinstoeckli для указания функций password_hash
. Я прочитал код, и в DEV_URANDOM
password_hash
которое я вижу, только разные вещи, это проверка ошибок и использование DEV_URANDOM
из ОС для генерации более случайной соли.
class PassHash { public static function rand_str($length) { $chars = "0123456789./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; //only allowed chars in the blowfish salt. $size = strlen($chars); $str = ""; for ($i = 0; $i < $length; $i++) $str .= $chars[rand(0, $size - 1)]; // hello zend and C. return $str; } public static function hash($input) { return crypt($input, "$2y$13$" . self::rand_str(22)); // 2y is an exploit fix, and an improvement over 2a. Only available in 5.4.0+ } public static function hash_weak($input) { return crypt($input, "$2a$13$" . self::rand_str(22)); } // legacy support, Add exception handling and fall back to <= 5.3.0 public static function compare($input, $hash) { return (crypt($input, $hash) === $hash); } }
Это то, что я всегда использовал. Предложение также является PHPass . Он проверен и проверен.
rand()
, а не источник из ОС, но это легко изменить.
Кроме того, нет реальной причины использовать SHA256
хеширование поверх bcrypt. SHA256
слаб и может быть сломан с относительно небольшим усилием 3 .
Кроме того, хеширование паролей является существенной практикой, но для истинной безопасности запустите все входные данные, по крайней мере, из словаря John the Ripper 1, чтобы удалить наиболее распространенные пароли и сообщить пользователю использовать другой пароль. Wordlists используются гораздо эффективнее, чем любая грубая сила из-за ужасно слабых паролей.
Длина – это все (без юмора), когда речь заходит о грубых паролях. Практически любой предустановленный взломщик будет настроен не на 12 символов, если не будет отредактирован конфиг. Если вы когда-либо видели сайт с «максимальной длиной» на паролях, не забудьте никогда не использовать там пароль, потому что у них нет никакой безопасности 4 .