Может ли кто-нибудь указать мне на хорошую реализацию хэшированного пароля PHP/MySQL?

после прочтения о соли password hashing Id, как реализовать простую версию для области администратора на сайт Im building.

Если у вас есть хорошие ссылки с кодом, который хорошо реализовал эту идею, я был бы признателен, если бы вы могли поделиться.

спасибо,

8 ответов


процесс регистрации: пользователь вводит пароль. Система генерирует значение соли из случайных данных (может быть хэшем времени & PID или что-то еще). Системы генерируют хэш-значение значения password & salt и сохраняют оба из них в таблице регистрации.

процесс входа: пользователь вводит пароль. Система извлекает значение salt из базы данных и хэширует его и пароль и сравнивает его со значением хэшированного пароля, введенным в базу данных во время регистрация.

пароль открытого текста никогда не хранится в базе данных. Значение salt никогда не видно клиенту.


Ну, вот что я бы сделал:

function makeToken($length = 16) {
    if ($length > 16) {
        $ret = '';
        while ($length > 0) {
            $ret .= makeToken(16);
            $length -= 16;
        }
        if ($length < 0) {
            $ret = substr($ret, 0, $length);
        }
        return $ret;
    }
    $stub = '';
    for ($i = 0; $i < 100; $i++) {
        $stub .= chr(mt_rand(1, 254));                
    }
    $hash = sha1($stub);
    $hashLen = strlen($hash);
    $ret = '';
    for ($i = 0; $i < $length; $i++) {
        $ret .= $hash[mt_rand(0, $hashLen - 1)];
    }
    return $ret;
}

function makeSaltedHash($string, $salt = '') {
    if (empty($salt)) { 
        $salt = makeToken();
    }
    $hash = '';
    for ($i = 0; $i < 200; $i++) {
        $hash = sha1($hash . $salt . $string);
    }
    return $hash . ':' . $salt;
}

function verifySaltedHash($string, $hash) {
    if (strpos($string, ':') === false) return false;
    list ($base, $salt) = explode(':', $hash);
    $test = makeSaltedHash($string, $salt);
    return $test === $hash;
}

рациональное это:

во-первых, генерируйте случайную соль (это всегда будет возвращать шестнадцатеричную строку, поэтому ее можно использовать для токенов и т. д.). Затем цикл над функцией хэширования (sha1 в этом случае) более 1 раза. Это так, что становится дороже генерировать радужную таблицу (200x как дорого в этом случае), добавляя относительно небольшие расходы на генерацию.

использование:

создать хэш:

$hash = makeSaltedHash($password);

для проверки хэша:

$bool = verifySaltedHash($password, $savedHash);

чтобы создать токен (защита CSRF, session_id и т. д.), Вы можете сделать это несколькими способами:

Фиксированной Длины:

$token = makeToken(32);

Случайный Длина:

$token = makeToken(mt_rand(64,128));

Edit: увеличение повторений на sha1 в функции хэширования.


function encodePwd($salt, $string) {
   return sha1( $salt . $string );
}

подумайте о рандомизации соли в течение минуты. Кодировка пароля в частности.

если у меня есть соль " random "и пароль" complex", мой sha1 будет

e55ec45f2873a04d2b888a5f59dd3f9d3bb25329

это хранится в базе данных. Я хочу проверить это.

поэтому, когда пользователь предоставляет мне "сложный" в качестве пароля, я помечаю "случайный" перед ним и кодирую его, чтобы получить тот же хэш. Если они равны, то Базинга! я готова.

но что, если это был случайный?

соль, когда она хранилась:"random"

SHA1: e55ec45f2873a04d2b888a5f59dd3f9d3bb25329

соль, когда пользователь положил его в: "apple"

SHA1: e07b207d77a0bd27d321552fc934b186559f9f42

как я собираюсь совпадают?

если вы ищете более безопасный метод, используйте данные, которые вы есть и это постоянный как имя пользователя или идентификатор пользователя или что-то (желательно что-то, что не изменится). Вам нужен образец, на который вы можете положиться.

имя пользователя будет работать хорошо (вы нужно обязательно обновить пароль, если они когда-либо меняли имя пользователя), таким образом аутентификация может выглядеть как

`WHERE `username` = '&username' AND `password` = '" . encodePwd( $username, $password ) . "'"`

function encodePwd( $username, $password) {
   // maybe modify username on a non-random basis? - like
   // $username = sha1( substr($username, 2)); // assuming usernames have a min-length requirement
   return sha1( $username  . $password ) ;
}

У меня нет ссылки на доступный код, но то, что я делал в прошлом, - это генерировать рандомизированную соль -$salt = rand(1,1000000000); - и сохраните его в сеансе. Я передаю эту соль на страницу входа в систему, а затем использую JavaScript для создания хэша SHA пароля salt+, который передается, а не пароль открытого текста. Поскольку соль хранится в сеансе, я могу использовать это, чтобы увидеть, соответствует ли хэш входа хэшу соли + пароля, хранящемуся в БД.


Если вам нужны действительно безопасные хэши, пожалуйста, используйте портативный PHP хеширования framework.

Я бы также рекомендовал это месяц статьи безопасности PHP это имеет дело с хэшированием паролей и безопасностью хэшей.


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

Я хэш-пароли, как это

$hash = sha1(strlen($password) . md5($password) . $salt);

Я думаю, что это лучшая производительность между скоростью и"безопасностью".

function salt($lenght = 9) {
    $numbers = '0123456789';
    $chars = 'qwertzuiopasdfghjklyxcvbnm';

    $password = '';
    $alt = time() % 2;
    for ($i = 0; $i < $length; $i++) {
        if ($alt == 1) 
        {
            $password .= $chars[(rand() % strlen($chars))];
            $alt = 0;
        } else 
        {
            $password .= $numbers[(rand() % strlen($numbers))];
            $alt = 1;
        }
    }
    return $password;
}

код прост, и Дэн хеберден уже предоставил его.

соль-это просто фрагмент текста, который вы добавляете или добавляете к паролю перед созданием хэша. например, если ваш пароль "пароль", а соль "соль", то хэш будет hashFunction('saltpassword') вместо hashFunction('password').

соли обычно используются, чтобы избежать трещин rainbow password - это где большой список паролей и их хэши проверяются против хэшированного пароля. например, в приведенном выше примере, скажем, есть хэш 123456, который соответствует hashFunction('password'), если злоумышленник знает, что ваш хэш 123456, то они знают, что ваш пароль "пароль".

соль должна быть случайной строки из букв и цифр - например kjah!!sdf986. очень маловероятно, чтобы у кого-то был радужный стол, включая kjah!!sdf986password поэтому, даже если кто-то получит ваш хэшированный пароль, это бесполезно.

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


не могли бы вы использовать встроенный crypt(...) функции?

... Использование...

crypt('rasmuslerdorf', '$rasmusle$')

... Результат...

MD5: $rasmusle$rISCgZzpwk3UhDidwXvin0

... Есть больше примеров и других методов хэша, доступных в документация.