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


Я использую функцию PHP crypt для хэширования/шифрования паролей, но я не думаю, что делаю это правильно, потому что "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 первый параметр-это строка (пароль), а второй-соль.

3 2

3 ответа:

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

Источник

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

Вы должны использовать password_hash() вместо crypt, по причинам, которые вы упомянули: "я, вероятно, даже не использую функцию 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']
));