Может ли кто-нибудь указать мне на хорошую реализацию хэшированного пароля 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
... Есть больше примеров и других методов хэша, доступных в документация.