Как правильно реализовать hash_hmac?

Читая этот отличный ответ о хешировании паролей, и задаваясь вопросом, как для его реализации:

Злая блоха написала:

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

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

Пример кода в исходном посте:

function hash_password($password, $nonce) {
  global $site_key;
  return hash_hmac('sha512', $password . $nonce, $site_key);
}

Как я могу подтвердить пароль с помощью этого кода? Позвольте мне объяснить:

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

Кстати, вы рекомендуете этот метод хеширования?


person fabrik    schedule 07.04.2011    source источник
comment
Вам не нужно выбирать пользователя, используя пароль в качестве критерия выбора. Просто выберите пользователя на основе уникальных характеристик, таких как адрес электронной почты или логин, а затем проверьте пароль. Также см. Связанный вопрос для некоторых идей хеширования (отказ от ответственности: я ответил на это): stackoverflow.com/questions/3787346/   -  person Arc    schedule 07.04.2011
comment
Кстати, выбор только по имени пользователя также имеет то преимущество, что вы можете отображать, что пользователь не существует или пароль недействителен в зависимости от ошибки, которая чрезвычайно увеличивает удобство использования вашего веб-сайта. Иногда вам приходилось использовать другое имя пользователя по какой-либо причине, и спустя долгое время вы могли попробовать старый и тонны паролей, потому что он просто говорит, что вход не удался. Если у пользователя нет ошибки, в этом нет необходимости.   -  person ThiefMaster    schedule 07.04.2011
comment
@Archimedix Спасибо за ответ. Кстати, извините, но я не вижу разницы между добавлением общесистемной соли к паролю в виде открытого текста или к ключу. Можете ли вы пролить на это свет?   -  person fabrik    schedule 07.04.2011
comment
Я ни в коем случае не специалист по криптографии, но, видя, что ваша соль - это то, что вы считаете своим секретным ключом для шифрования пароля пользователя (то есть секретным для пользователя), я бы использовал только соль в ключе HMAC и поставил пароль в части сообщения. Таким образом, пользователь не может влиять на ключ HMAC для запуска дифференциальных атак.   -  person Arc    schedule 08.04.2011
comment
И да, пользователь с улучшенным удобством использования не существует - это недостаток безопасности, как справедливо сказал Лаас, поскольку он позволяет злоумышленнику составить список действительных учетных записей пользователей. Здесь вы можете отличить сайты с плохой безопасностью от сайтов с возможно не очень плохой безопасностью. Тем не менее, атаки на основе времени по-прежнему могут использоваться для определения того, какие учетные записи могут быть действительными, однако с ограниченной уверенностью - для сайта с большим количеством активных пользователей трудно сказать, вызвано ли разное время загрузки поиском несуществующих пользователей или неверный пароль.   -  person Arc    schedule 08.04.2011


Ответы (1)


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

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

SELECT * FROM users WHERE email = 'email' AND password = SHA1(CONCAT('cleartextpass',nonce));

Или вы можете провести математику в коде после получения всех совпадающих писем.

РЕДАКТИРОВАТЬ: комментарий ThiefMaster о различении между отсутствующим пользователем и недопустимым паролем является классическим недостатком безопасности, который позволяет злоумышленникам получить список действительные имена пользователей и сосредоточьтесь на взломе их паролей вместо того, чтобы ловить рыбу в темноте. Я настоятельно рекомендую против этого.

person Laas    schedule 07.04.2011
comment
не могли бы вы объяснить свой ответ немного подробнее? Не совсем понятно, откуда в вашем запросе берется nonce. В принципе, ваше решение мне кажется лучше, потому что оно может быть выполнено только с помощью запроса к базе данных. - person fabrik; 07.04.2011
comment
В запросе SQL nonce - это имя столбца таблицы (обратите внимание, оно не заключено в кавычки). Это означает, что CONCAT () берет пароль в виде открытого текста и добавляет к нему все, что когда-либо хранится в поле nonce - person Laas; 07.04.2011
comment
и я могу сгенерировать ключ SHA1 в SQL и PHP, я прав? Могу ли я использовать это поле nonce для других целей? Токен утерянного пароля и т. Д.? Или это будет брешь в безопасности? - person fabrik; 07.04.2011
comment
@fabrik - (1) да, вы можете генерировать хеши в любом из них, если оба поддерживают один и тот же алгоритм (например, MySQL не имеет HMAC). (2) Это двоякое: цель одноразового номера - получить разные хэши для одинаковых паролей. Таким образом, зная одноразовый номер, злоумышленник может уменьшить пул строк, которые необходимо просмотреть, при грубом форсировании. С другой стороны, злоумышленник может извлечь выгоду из одноразового номера только тогда, когда у него есть фактический хэш пароля, и в этом случае он, вероятно, все равно имеет одноразовый номер (из дампа SQL и т. Д.). HMAC смягчает все это, вводя site_key. - person Laas; 07.04.2011
comment
Мой последний комментарий не следует читать, что я рекомендую отправлять одноразовый номер - вы всегда в большей безопасности, чем меньше знает злоумышленник. - person Laas; 07.04.2011