Почему функция 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 ответа:
Стандартный 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'] ));