Хеширование пароля, от сломанных методов до самых безопасных сейчас

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

чем я не верил в md5 и хотел использовать шифрование sha1,sha256,sha512. Но проблема в том, что теперь у меня есть пароли в зашифрованном виде, который

md5("password"+"salt")

в тот момент я не знал пароль пользователей.И что я сделал?

sha1(md5("password"+"salt"))

Теперь после нескольких раз в этом поле я обнаружил, что sha1 также не слишком безопасен и сломан что я должен сделать, это использовать bcrypt (), чтобы сделать пароль безопасным .

Так что теперь я буду использовать

 crypt(sha1(md5("password"+"salt")))

пароль теперь очень безопасен, но основная проблема по-прежнему заключается в том, что время, которое он будет использовать для создания хэш-значения, всегда будет больше, чем использовать bcrypt("пароль")

Теперь, что я хочу сказать, предположим, если bcrypt взломан и найден сломанным и в будущем появляется новая криптографическая функция, которая является более безопасной и. Чем этот способ создания пароля из старых значений всегда будет отнимать много времени.

какое может быть решение для этого. как я знаю, рассылка пользователей для смены пароля не всегда 100% успешна. Другое дело, чтобы добавить новое поле в базе данных, которые хранят новые хэшированные значения и если все поля заполнены, чем удалить значения md5 из БД .Но вещь таким образом предыдущие хэшированные значения все еще видимый.

Так это будет продолжаться, или у вас, ребята, есть какое-то решение. :)

3 ответов


PHP 5.5 представляет API паролей который решает эту проблему:

новый безопасный пароль хэширования API в PHP 5.5

RFC для нового простого в использовании API хэширования паролей только что был принят для PHP 5.5. Поскольку сам RFC довольно технический, и большинство примеров кодов-это то, что вы не должны использовать, я хочу дать очень быстрый обзор нового API:

зачем нам нужен новый API-интерфейс?

все знают, что вы должны хэшировать свои пароли с помощью bcrypt, но все же удивительное количество разработчиков использует небезопасные хеши md5 или sha1 (просто посмотрите на недавние утечки паролей). Одна из причин этого заключается в том, что API crypt() смехотворно сложен в использовании и очень подвержен ошибкам программирования.

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

как хэш пароли

создание хэшей паролей не может быть проще, чем это:

  $hash = password_hash($password, PASSWORD_DEFAULT);

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

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

$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);

проверка паролей

проверка паролей так же просто:

<?php
// $password from user, $hash from database
if (password_verify($password, $hash)) {
    // password valid!
} else {
    // wrong password :(
}

помните: соль и алгоритм являются частью хэша, поэтому вам не нужно предоставлять их отдельно.

перефразируя пароли

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

делать это тоже очень просто:

<?php
function password_verify_with_rehash($password, $hash) {
    if (!password_verify($password, $hash)) {
        return false;
    }

    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $hash = password_hash($password, PASSWORD_DEFAULT);

        // update hash in database
    }

    return true;
}

приведенный выше фрагмент сохранит ваши хэши в актуальном состоянии с PHP по умолчанию. Но еще раз вы также можете указать пользовательские параметры, например password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12']).

уровень совместимости для старых версий PHP

новый API будет введен только в PHP 5.5, но вы уже можете использовать реализацию PHP того же API сейчас! Реализация совместимости автоматически отключится после обновления до 5.5.


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

(что сказал, перефразируя Брюса Шнайера, " атаки только когда-либо get better", поэтому начинаем переходить от MD5 к более надежным хэш-функциям, таким как ша-2 или ша-3, Это конечно не плохая идея, даже если вы не нужно это сделать.)

подвох в том, что MD5 только не подходит для хэширования паролей по двум причинам, обе из которых на самом деле являются преднамеренными функциями дизайна (и разделяются другими хэш-функциями, такими как SHA-2 и SHA-3):

  1. MD5 является детерминированные, что означает, что хэширование одного и того же входа с MD5 всегда производит один и тот же выход.

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

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

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

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

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

hash = salt + bcrypt( sha1( md5( password + salt ) ) )

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


Так что вы должны обновить все пароли пользователей в базе? Если вы twit свой сценарий входа в систему вам не придется ничего делать вообще. Взгляните на это:

обновление хэша пароля Md5 до хэша BCRYPT::

$passwordFromDatabase = "0d107d09f5bbe40cade3de5c71e9e9b7"; // md5  hash of "letmein"
$passwordFromForm = $_POST['password']; // $_POST['password'] == "letmein"

if(password_needs_rehash($passwordFromDatabase, PASSWORD_BCRYPT, ["cost" => 12]) && md5($passwordFromForm) === $passwordFromDatabase){
    // generate new password
    $newPasswordHash = password_hash($passwordFromForm, PASSWORD_BCRYPT, ["cost" => 12]);
    // update hash from database - replace old hash $passwordFromDatabase with new hash $newPasswordHash
    // after update login user
    if(password_veryfi($passwordFromForm, $newPasswordHash)){
        // user has logged in successfully and hash was updated
        // redirect to user area
    }else{
        // ups something went wrong Exception
    }
}else{
    if($password_veryfi($passwordFromForm, $passwordFromDatabase)){
        // user password hash from database is already BCRYPTed no need to rehash
        // user has logged in successfully
        // redirect to user area
    }else{
        // wrong password
        // no access granted - stay where you are
    }
}

приведенный выше пример является универсальным. Вместо

... && md5 ($passwordFromForm)===...){

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

МЕДЛЕННО ALGOTITHM

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

  • PBKDF2 с - это просто итерационный быстрый хэш (т. е. все еще эффективно распараллелить). (Это схема, которая может использоваться с различными базовый алгоритм. Используйте любой алгоритм, который вы используете в любом случае система.)
  • Bcrypt нужна некоторая (4KB) рабочая память, и таким образом менее эффективно реализуемый на GPU с менее чем 4KB кэша на процессор.
  • скрипт использует (конфигурируемый) большой объем памяти дополнительно к время обработки, которое делает его весьма дорогим распараллелить дальше Графические процессоры или пользовательское оборудование, в то время как "нормальные" компьютеры обычно имеют достаточно Доступной оперативной памяти.

ХОРОШИЙ ПАРОЛЬ

длина пароля не должна быть менее 8 символов и он должен использовать по крайней мере один:

  • верхний регистр
  • один номер и
  • один специальный символ

настройка пароля 8 char long с нижним и верхним регистром и специальным символом способна создавать: 6 634 204 312 890 625 комбинаций. Однако, если ваш пароль будет неделю Пусть говорят 6 символов маленькие буквы только вы получите только: Комбинация 308,915,776. Чтобы сделать вашу учетную запись безопасной, рекомендуется использовать более 12 символов для длины пароля. нажмите для подсчета комбинаций паролей Симулятор

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

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

эта программа IGHASHGPU v0.90 утверждает, что может делать около 1300 миллионов хэшей SHA-1 (т. е. более 2^30) в каждую секунду на одном GPU ATI HD5870.

предположим a пароль из 40 бит энтропии, это 2^10 секунд, что составляет около 17 минут.

пароль из 44 бит энтропии (как в знаменитом комиксе XKCD) занимает 68 минут (в худшем случае, средний случай составляет половину этого).

запуск на нескольких графических процессорах параллельно ускоряет это пропорционально.

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

решение

вы можете настроить скорость вашего алгоритма, манипулируя его стоимость. Чем выше стоимость, тем дольше потребуется кодировать и кодировать ваш пароль. Лучше всего было бы, вероятно, стремиться к 500 mls, что затрудняет атакующим грубую силу нашего пароля.

пароль с 12 char и более длинным + более медленным алгоритмом гарантирует приличное количество комбинации, чтобы быть грубым, прежде чем пароль будет взломан. Как только у нас есть достойный пароль, мы можем сделать жизнь намного сложнее для тех, кто хочет войти в нашу систему, замедляя процесс проверки пароля до чего-то, что сделает его действительно сложным и трудоемким. Установите стоимость на число, которое повлияет на время проверки пароля пользователя около 0,5 С.

НАСТРОЙКА СЕБЕСТОИМОСТИ

как вы знаете, как высоко вы должны установить стоимость с момента выполнения сценария будет ли отличаться для каждого сервера на основе вычислительной мощности и trafic ?

Ну, вы должны измерить время, необходимое для процесса проверки и настроить стоимость, как это подходит для вас.

<?php
/**
 * This code will benchmark your server to determine how high of a cost you can
 * afford. You want to set the highest cost that you can without slowing down
 * you server too much. 8-10 is a good baseline, and more is good if your servers
 * are fast enough. The code below aims for ≤ 50 milliseconds stretching time,
 * which is a good baseline for systems handling interactive logins.
 */
$timeTarget = 0.50; // 500 milliseconds 

$cost = 8; //start to measure from cost = 8
do {
    $cost++;
    $start = microtime(true);
    password_hash("Ajd_hsk-K87&", PASSWORD_BCRYPT, ["cost" => $cost]);
    $end = microtime(true);
} while (($end - $start) < $timeTarget);

echo "Appropriate Cost Found: " . $cost . "\n";
?>

ссылка

вышеуказанная функция возвратит номер КС цены которую нам нужно использовать для того чтобы соотвествовать наши безопасности.

Appropriate Cost Found: 13 //this result will be different based on your server machine.

этот скрипт взят из руководства php и улучшен для обработки в 10 раз дольше. Этот в большинстве случаев это был бы безопасный способ, но для входа admin и super admin я бы подумал, чтобы сделать его еще более трудоемким (что-то о 1s), так как эти места представляют больший интерес для реальных хакеров.