Как использовать алгоритм Argon2 с password_hash?

Итак, я слышал, что PHP 7.2 представил новый алгоритм Argon2. Но я не понимаю, как я могу использовать его с моим существующим кодом. Например, у меня есть это

$password = password_hash('somepassword', PASSWORD_DEFAULT, ['cost' => 12]);

PASSWORD_DEFAULT теперь использует Argon2? Что, если что, мне нужно изменить с помощью password_verify? Считается ли сейчас bcrypt небезопасным?


person Machavity♦    schedule 01.12.2017    source источник


Ответы (2)


What is Argon2? Is bcrypt bad now?

До PHP 7.2 использовался только алгоритм хеширования password_hash bcrypt. На момент написания этой статьи bcrypt по-прежнему считается сильным хешем, особенно по сравнению со своими предшественниками md5 и sha1 (оба являются небезопасным, потому что они быстрые). Argon2 - это просто более затратный алгоритм для грубой силы

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

Bcrypt по-прежнему является приемлемым хешем для паролей. Нет необходимости переключаться, если вы этого не хотите (начиная с версии 7.2.0). Кроме того, PASSWORD_DEFAULT следует изменять только (согласно PHP Internals policy) в следующей полной версии (7.3.0 или выше). Если вы хотите, чтобы вы продолжали использовать только bcrypt, вы можете использовать вместо этого PASSWORD_BCRYPT. Однако в этом нет необходимости, как мы обсудим ниже.

How do you use Argon2?

Сначала мы переключим второй аргумент password_hash на один из этих констант.

  • PASSWORD_ARGON2I - PHP 7.2.0+
  • PASSWORD_ARGON2ID - PHP 7.3.0+ (предпочтительно, если доступно, см. Примечания ниже)

а затем нам нужно будет изменить наши параметры. bcrypt использует cost в качестве параметра, указывающего, сколько раз он перебирает пароль (более высокая стоимость = более длительное время хеширования). Однако есть разные факторы стоимости.

password_hash('somepassword', PASSWORD_ARGON2I, ['memory_cost' => 2048, 'time_cost' => 4, 'threads' => 3]);

Из руководства мы посмотри, что делают эти варианты

  • memory_cost - Максимальный объем памяти (в кибибайтах), который может быть использован для вычисления хэша Argon2 (по умолчанию 1024)
  • time_cost - Максимальное количество времени, которое может потребоваться для вычисления хэша Argon2 (по умолчанию 2)
  • threads - Количество потоков, используемых для вычисления хэша Argon2 (по умолчанию 2)

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

Также обратите внимание, что, хотя bcrypt хранит 60 символов, Argon2 может потребовать больше. В идеале вы должны сделать так, чтобы ваше поле пароля содержало 255 символов.

What do we change in password_verify?

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

//Works for both bcrypt and Argon2
if(password_verify($user_password, $stored_hash)) {
    // password validated
}

Если вы хотите обновить хэши из bcrypt, вы можете сделать это, когда пользователь успешно войдет в систему (и, таким образом, предоставит вам нехешированный пароль). Просто проверьте, начинается ли ваш хеш с $2y$ (маркер bcrypt). Если это так, передайте предоставленный пароль в password_hash снова, но с аргументами Argon2, и сохраните его в поле пароля вошедшего в систему пользователя.

What is Argon2ID?

Представленный в PHP 7.3, Argon2ID вносит некоторые улучшения по сравнению с Argon2I, как указано в этом Вопрос по Crypto.SE

Лучшая атака компромисса на однопроходный Argon2id - это комбинированная атака с низким объемом памяти (для первой половины памяти) и ранжирующая атака (для второй половины), которые объединяют коэффициент примерно 2,1.

Argon2ID работает с теми же аргументами, с которыми работает Argon2I.

person Machavity♦    schedule 01.12.2017
comment
В этом ответе было бы полезно добавить, как загрузить Argon2 в модули времени выполнения PHP. Ваш ответ подразумевает, что PHP 7.2 имеет его по умолчанию, тогда как я могу показать только в своих настройках, что PHP 7.1 не, Ура - person Martin; 03.01.2018
comment
@Martin Нет модуля для загрузки. Если вы используете 7.2.0 или более позднюю версию, она есть (password_hash - это ядро ​​PHP). Я не знаю ни о каких вариантах резервного копирования, если вы это имеете в виду. - person Machavity♦; 03.01.2018
comment
Вместо проверки того, с чего начинается строка, вам, вероятно, следует использовать php.net /manual/en/function.password-needs-rehash.php as Эта функция проверяет, реализует ли предоставленный хэш предложенный алгоритм и параметры. - person jeroen; 13.09.2018
comment
что более высокая стоимость здесь замедлит ваш скрипт. Это происходит только во время процесса password_hash() ИЛИ password_verify()? - person Irfandy Jip; 19.12.2018
comment
@IrfandyJip Оба. Помните, что password_verify принимает все параметры хэша и пароля для проверки и генерирует новый хэш. Если новый хэш (с такими же точными параметрами) совпадает со старым, пароль проверяется. - person Machavity♦; 19.12.2018
comment
Это memory_cost и time_cost обязательно? Или мы можем просто сделать password_hash ("somepassword" , PASSWORD_ARGON2ID)? - person SilverSurfer; 12.07.2019
comment
@SilverSurfer Затраты не требуются. Если вы не указываете значения, PHP использует значение по умолчанию - person Machavity♦; 12.07.2019

Только если вы используете PHP 7.3: я создал две простые и тонкие функции для использования Argon2ID с PHP:

function argon2idHash($plaintext, $password, $encoding = null) {
    $plaintextsecured = hash_hmac("sha256", $plaintext, $password);
    return $encoding == "hex" ? bin2hex(password_hash($plaintextsecured, PASSWORD_ARGON2ID)) : ($encoding == "base64" ? base64_encode(password_hash($plaintextsecured, PASSWORD_ARGON2ID)) : password_hash($plaintextsecured, PASSWORD_ARGON2ID));
}

function argon2idHashVerify($plaintext, $password, $hash, $encoding = null) {
    $plaintextsecured = hash_hmac("sha256", $plaintext, $password);
    return password_verify($plaintextsecured, $encoding == "hex" ? hex2bin($hash) : ($encoding == "base64" ? base64_decode($hash) : $hash)) ? true : false;
}

Чтобы получить хешированное значение, используйте (последний параметр является необязательным, вы можете выбрать шестнадцатеричный, base64 или ничего) [return = ›string]:

$salt = "LALALA";
argon2idHash($clearvalue, $salt, "hex"); // with encoding
argon2idHash($clearvalue, $salt); // without encoding

Для проверки использования хешированного значения (параметр $ salt должен соответствовать солевому, установленному во время хеширования, то же правило применяется к кодированию, если оно используется) [return = ›bool]:

$salt = "LALALA";
argon2idHashVerify($clearvalue, $salt, $hashtoverify, "hex") ? "match" : "dont match"; // with encoding
argon2idHashVerify($clearvalue, $salt, $hashtoverify) ? "match" : "dont match"; // without encoding

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

person Marco Concas    schedule 17.09.2020
comment
Функция, которую я создал как единственное, преобразует текст, который будет зашифрован в sha256-hmac с выбранным вами паролем или солью, затем используется стандартная функция аргона. Мой - дополнительный шаг, который дает дополнительную безопасность. Теперь вы говорите, что аргон 2 безопасен, и мы увидим через несколько лет, сколько он будет стоить. Я не считаю это действительным для вашей мотивации "против". - person Marco Concas; 13.03.2021