Почему функция crypt () PHP возвращает одно и то же для двух разных строк?

Я использую функцию crypt PHP для хэширования / шифрования паролей, но я не думаю, что делаю это правильно, потому что «nathan12» и «nathan123» позволяют мне войти в мою учетную запись в моей системе (фактический пароль – «nathan123» », и поэтому« nathan12 »или что-то еще НЕ разрешить мне входить в систему).

Вот что делает моя система, когда пользователь регистрируется:

 [...] $salt = uniqid(mt_rand(), true); $password = crypt($password, $salt); // '$password' is the inputted password $insertUserStmt = $mysqli->prepare("INSERT INTO users (name, username, password, password_salt, email, created) VALUES (?, ?, ?, ?, ?, ?)"); $insertUserStmt->bind_param("sssssi", $name, $username, $password, $salt, $email, time()); $insertUserStmt->execute(); [...] 

Он вставляет хэшированный / зашифрованный пароль (пароль $password ) в базу данных вместе с $salt .

Когда кто-то пытается войти в систему, выполняется следующее, чтобы проверить, вводит ли пользователь правильный пароль для имени пользователя, которое они ввели:

 [...] // $password_salt is from DB; $password is inputted password $password_crypt = crypt($password, $password_salt); // $login_password is from DB if($password_crypt == $login_password) { [...] 

Я, вероятно, даже не использую функцию crypt должным образом, но, согласно документам PHP, первым параметром является строка (пароль), а вторая – соль.

В стандартном DES-based crypt() […] используются только первые восемь символов str , поэтому более длинные строки, начинающиеся с тех же восьми символов, будут генерировать тот же результат (когда используется одна и та же соль).

источник

Используйте соль, которая начинается с $<algo>$ чтобы использовать что-то другое, кроме DES. Подробнее см. Документацию crypt() .

Вы должны использовать password_hash () вместо crypt, по причинам, которые вы упомянули: «Возможно, я даже не использую функцию склепа должным образом». Вы говорите, что получаете соль из БД … это звучит небезопасно. с password_hash () вы можете позволить PHP обрабатывать соление для вас безопасным образом.

Подробнее о том, почему это стоит: http://www.sitepoint.com/hashing-passwords-php-5-5-password-hashing-api/

Для шифрования паролей вы должны использовать больше, чем просто соль для пароля.

Вы можете сохранить случайную строку в файле конфигурации.

 $config['passwordKey'] = 'asjdfa783#H$Khjsdfhas78a734J%JSDGK2348235hxmfdA'; 

И добавьте его в $salt при шифровании. Таким образом, если база данных скомпрометирована, а вашей файловой системы нет, тогда злоумышленники не смогут расшифровать хэши паролей базы данных. Это должно быть важно для защиты информации пользователей на других сайтах с идентичной информацией для входа.


Для хеширования ваших паролей password_hash – простая оболочка crypt() специально настроенная для хэширования паролей! ( источник )

 $password = password_hash($password, PASSWORD_BCRYPT, array( 'cost' => 60, 'salt' => $salt . $config['passwordKey'] ));