Подтвердить что ты не робот

Как реализовать соль в моем логине для паролей?

Я хочу реализовать соль в моей системе входа, но немного запутался в том, как это должно работать. Я не могу понять логику этого. Я понимаю, что md5 - это односторонний алгоритм, и все функции, с которыми я столкнулся, кажутся хэшными все вместе. Если это так, как получить пароль для сравнения? Мой самый большой вопрос заключается в том, как солить пароль пользователей безопаснее, чем просто хешировать пароль? Если база данных когда-либо подвергалась риску, хэш вместе с солью находится в базе данных. Разве это не все, что понадобится хакеру?

Я также нашел здесь еще одно сообщение о SO, где другой разработчик сказал:

"Убедитесь, что соль и алгоритм хранится отдельно от базы данных

Я хотел бы сохранить соль в базе данных. Это действительно проблема, если я это делаю?

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


EDIT: Я хочу поблагодарить всех за их ответы и идеи. Несмотря на то, что теперь я могу быть более смущенным, это, безусловно, было для меня опытом обучения. Еще раз спасибо ребятам.

4b9b3361

Ответ 1

Хеш-функция всегда возвращает одно и то же значение для той же входной строки. Скажем, у моего пользователя (Алисы) есть пароль secret. Хеширование secret с помощью md5() приводит к следующему хешу

5ebe2294ecd0e0f08eab7690d2a6ee69

Используя словарь (список общих слов и пароля) или один из различных сайтов, предлагающих вам эту услугу, злоумышленник (Мэллори) может легко узнать, что пароль секретен, когда он видит в своем словаре, что 5ebe2294ecd0e0f08eab7690d2a6ee69 = secret.

Процесс соления перед хешированием затрудняет использование словарной атаки, не зная вашу соль. Рассмотрим следующее:

<?php
$salt = '@!#%[email protected]#[email protected],[email protected]#@!';
$hash = md5($salt . 'secret');

В результате хеш теперь b58ad809eece17322de5024d79299f8a, но пароль Алисы по-прежнему secret. Теперь, если Мэллори возьмет руки за соленый хеш, скорее всего, она не найдет ответа в своем словаре. Если она это сделает, словарь даст ей неправильный ответ.

Никогда не храните статическую соль в своей базе данных. Желательно сохранить его с помощью вашей конфигурации приложения (которая, кстати, не должна быть доступна из Интернета).

Если вы собираетесь использовать динамическую соль, вам понадобится использовать базу данных. Используйте не нулевой столбец существующих достоверных данных для создания соли (строка с зашифрованной зашифрой имени пользователя на основе секретного ключа шифрования обычно криптографически безопасна). Не используйте отдельную колонку для соли. Если вы не можете использовать существующий столбец, включите соль в том же столбце, что и ваш хэш. Например, используйте первые 32 символа для вашей 128-битной соли, а затем последние 40 для вашего 160-битного хэша. Следующая функция генерирует такой хеш:

function seeded_sha1($string, $seed_bits) {
    if(($seed_bits % 8) != 0) {
        throw new Exception('bits must be divisible by 8');
    }

    $salt = '';
    for($i = 0; $i < $seed_bits; $i+=8) {
        $salt .= pack('c', mt_rand());
    }

    $hexsalt = unpack('h*hex', $salt);

    return $hexsalt['hex'] . sha1($salt . $string);
}

function compare_seeded_sha1($plain, $hash) {
    $sha1 = substr($hash, -40);
    $salt = pack('h*', substr($hash, 0, -40));

    $plain_hash = sha1($salt . $plain);
    return ($plain_hash == $sha1);
}

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

Примечание. Существуют другие типы атак на md5(), поэтому вы используете более безопасные алгоритм хэширования, sha1(). Или, еще лучше, используйте переносимый PHP-хэш-хеширование, который был разработан с учетом безопасности и обратно совместим с почти любым PHP версия.

require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hashed stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

Ответ 2

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

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

Хранение солей отдельно не требуется, чтобы получить это преимущество. Теоретически это было бы еще более безопасно, потому что это нейтрализовало бы слабость словаря или короткие пароли. На практике это не стоит беспокоиться, потому что в конце дня вам нужно получить доступ к солям где-нибудь, чтобы проверить пароли. Кроме того, попытка отделить их приведет к более сложным системам - и чем сложнее система, тем больше возможностей для дыр в безопасности.

Изменить: Мои конкретные рекомендации:

  • Генерировать длинную псевдослучайную соль для каждого пользователя и хранить в БД
  • Используйте хэш-код на основе bcrypt
  • в идеале, не реализуйте его самостоятельно, используйте существующую библиотеку вместо

Ответ 3

Забудьте об использовании солей (частично по той причине, что вы упомянули), вместо этого используйте bcrypt:

Для хорошего объяснения см.: http://codahale.com/how-to-safely-store-a-password/

Ответ 4

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

Вы можете использовать ту же соль для каждого пользователя вместе с хорошей идеей Juraj, чтобы совместить пароль с другими неизменяемыми полями базы данных (уникальными для пользователя). Но будьте осторожны, потому что эта информация привязана к паролю. Если вы хотите хэшировать имя пользователя + пароль вместе, чтобы гарантировать уникальный хеш, вы не сможете изменить имя пользователя, не создавая нового пользователя и не требуя, чтобы он установил новый пароль.

В качестве примера наличия уникальной соли для каждого пользователя и сохранения ее вместе с хэшем пароля, я укажу /etc/shadow на вашей типичной системы Linux.

[email protected]:/root# cat /etc/shadow | grep root
root:$1$oL5TTZxL$RhfGUZSbFwQN6jnX5D.Ck/:12139:0:99999:7:::

Здесь oL5TTZxL - соль, а RhfGUZSbFwQN6jnX5D.Ck/ - хэш. В этом случае пароль с открытым текстом является корневым, а хэш-алгоритм, который использует моя система, - это алгоритм пароля BSD на основе MD5. (более новые системы, чем у меня, имеют лучшие алгоритмы хеширования)

Ответ 5

Вы не получите пароль для сравнения. Вы шифруете пароль при попытке входа в систему и сравниваете сохраненное значение с новым зашифрованным значением.

Ответ 6

Как вы упомянули, алгоритмы хэширования работают только в одну сторону (или только если они достаточно сильны: -D)

Для вашего вопроса о солярии я бы рекомендовал хешировать пароль со строкой static salt и некоторыми динамическими данными из базы данных, которые должны не меняться strong > после создания

Это очень безопасный способ хранения паролей, так как даже если база данных скомпрометирована, хакерам/взломщикам по-прежнему необходимо получить статический строковый хэш и нужно угадать, как вы применили все соления.

Например, скажем, у вас есть таблица users с этими столбцами:

id
username
password
created_at

столбцы id и created_at после заполнения никогда не должны меняться.

поэтому, когда вы вводите пароль пользователя, вы можете сделать так просто, как:

<?php
    $staticSalt = '[email protected];ap][';
    $userPass = 'my new pass';
    // assuming $user variable is already populated with DB data
    // we will generate new hash from columns and static salt:
    $genPass = sha1($user['id'] . $userPass . $user['created_at'] . $staticSalt);
?>

Я надеюсь, что это поможет:) cheers

Ответ 7

Хеширование паролей предназначено, чтобы держать эти пароли в секрете от ваших собственных администраторов.

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

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

3) У каждого пользователя может быть отдельная соль: база данных будет использоваться для хранения соли, а хэш - из комбинации паролей/солей. Это предотвратит атаку радуги, но атаки грубой силы все же будут возможны.

4) Наконец, вы можете сохранить свою хэш-функцию в секрете, используя ограниченное по скорости аппаратное решение хэширования.

Это так хорошо, как вы можете. Из-за человеческой природы пароли имеют ограниченный домен и уязвимы для нападений грубой силы. Мы пытаемся запретить администраторам удерживать пароли пользователей, а затем использовать их в других системах, к которым у них не должно быть доступа.

Некоторые другие примечания:

a) Вы можете использовать bcrypt для комбинации паролей и солей, чтобы замедлить атаку грубой силы атакующего. Но поскольку мы принимаем администраторов, они могут быть терпеливыми.

b) Сохранение соли отдельно от хэша паролей не является эффективной защитой, мы все-таки принимаем администраторов.

c) Использование существующих данных в виде соли немного лучше, но я сомневаюсь, что существующие данные имеют такую ​​же энтропию, как у случайной соли.

Ответ 8

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

Например, если хакер получает доступ к вашей базе данных, а пароли не солены, то он может искать хеши в своей базе данных хэшей (см. http://en.wikipedia.org/wiki/Rainbow_table), чтобы получить исходные пароли.