Что я делаю не так с этой аутентификацией bcrypt на основе crypt()?

Я написал этот код почти дословно из множества очень полезных ответов здесь, на SO, поэтому я не могу понять, что не так.

Во-первых, вот моя функция для создания учетной записи пользователя:

function BFcrypt($password,$cost)
{
    $chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt=sprintf('$2a$%02d$',$cost);
    for($i=0;$i<22;$i++) $salt.=$chars[rand(0,63)];
    return array(
            'salt'=>$salt,
            'hash'=>crypt($password,$salt)
            );
}

Затем, когда пользователь заходит в систему:

case 'login':
    $login  =$_POST['login'];
    $pwd    =$_POST['pwd'];
    $sql    ="SELECT * FROM `users` WHERE `users`.`login`='$login' LIMIT 1;";
    if($query = mysql_query($sql)){
            $row=mysql_fetch_assoc($query);
            print_r($_POST);
            print_r($row);
            $hash = $row['password'];
            if(crypt($pwd,$hash)==$hash){
                echo"SUCCESS";
            }else{
                echo"FAILURE";

            }
    }

Функция входа в систему, похоже, всегда дает сбой. Я установил его так, чтобы он показывал мне $ pwd, $ hash и crypt($pwd,$hash), и по некоторым причинам crypt ($ pwd, $ hash) никогда не выглядит == $hash.

Вот строка в базе данных для примера пользователя (сейчас я регистрирую соль, хотя я знаю, что она должна быть включена в хеш:

'id'=>'680',
'login'=>'argh',
'password'=>'$2a$10$BWZAX7wrwQp5iyK4kh6VLunqy82eiXg7GaDs6mJLqdgT5s2qiUqYW',
'salt'=>'$2a$10$BWZAX7wrwQp5iyK4kh6VL5',
'first'=>'argh',
'last'=>'argh',
'zip'=>'00000',
'email'=>'argh',
'date updated'=>'2012-12-12 16:05:29'

Я считаю, что когда я вызываю crypt($pwd,$hash), он усекает $ hash, оставляя только исходную 22-символьную соль (плюс префикс), таким образом, результат будет таким же, как у $ hash, пока $ pwd является так же. Я ясно вижу, что здесь есть проблема в том, что соль, которую я записываю, на один символ длиннее, чем та, которая в итоге добавляется к хешу, но это подходящая длина для blowfish, и, в любом случае, сделать ее на один символ короче не так. кажется, чтобы помочь.

Я не могу понять, что я делаю здесь не так. Любая помощь будет оценена.

1 ответ

Решение

На основании вашей собственной соли и пароля 'argh' Я запустил небольшой тестовый скрипт:

$hash = crypt('argh', '$2a$10$BWZAX7wrwQp5iyK4kh6VL5');
// $2a$10$BWZAX7wrwQp5iyK4kh6VLuIzJHihvZTdfpRXNkTPVKkTiGfLDl1RO

var_dump(crypt('argh', $hash) == $hash);
// bool(true)

Кажется, проблема не в коде, который вы показали.

Вы можете проверить ширину поля базы данных, чтобы сохранить хэш пароля, который должен быть не менее 60. И пока вы работаете над этим, исправьте уязвимость SQL-инъекций (лучше всего использовать подготовленные операторы).

Другие вопросы по тегам