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

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

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

Спасибо,

Ответы [ 8 ]

6 голосов
/ 08 июня 2010

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

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

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

3 голосов
/ 08 июня 2010

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

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 раза. Это связано с тем, что создание радужного стола становится более дорогостоящим (в данном случае это в 200 раз дороже), при этом добавляя относительно небольшие затраты на генерацию.

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

Чтобы создать хеш:

$hash = makeSaltedHash($password);

Чтобы проверить хеш:

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

Чтобы сгенерировать токен (CSRF-защита, session_id и т. Д.), Вы можете сделать это несколькими способами:

Фиксированная длина:

$token = makeToken(32);

Случайная длина:

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

Редактировать: Увеличены повторения на sha1 в функции хеширования.

3 голосов
/ 08 июня 2010
function encodePwd($salt, $string) {
   return sha1( $salt . $string );
}

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

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

e55ec45f2873a04d2b888a5f59dd3f9d3bb25329

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

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

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

соль при хранении: «случайная»

SHA1: e55ec45f2873a04d2b888a5f59dd3f9d3bb25329

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

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 ) ;
}
2 голосов
/ 08 июня 2010

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

1 голос
/ 08 июня 2010

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

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

0 голосов
/ 08 июня 2010

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

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

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

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

MD5: $1$rasmusle$rISCgZzpwk3UhDidwXvin0

... В документации .

есть другие примеры и другие методы хеширования.
0 голосов
/ 08 июня 2010

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

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

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

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

0 голосов
/ 08 июня 2010

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

Я хэширую пароли вроде этого

$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;
}
...