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

Хеширование паролей - как обновить?

Там много обсуждение по лучшему алгоритму - но что, если вы уже в производстве? Как вы обновляетесь без использования reset для пользователя?


ИЗМЕНИТЬ/ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Несмотря на то, что я изначально хотел получить решение "быстро исправить" и выбрал orip response, я должен признать, что если безопасность в вашем приложении достаточно важна, чтобы даже беспокоиться об этой проблеме, то быстрое исправление - это неправильный менталитет и его предлагаемое решение, вероятно, неадекватно.

4b9b3361

Ответ 1

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

0:ab0123fe

то при обновлении до SHA-1 вы набросаете номер версии на 1:

1:babababa192df1312

(нет, я знаю, что эти длины, вероятно, неверны).

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

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

Ответ 2

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

Итак, если ваши существующие хэши являются прямыми MD5, и вы планируете перейти в какую-то форму PBKDF2 (или bcrypt или scrypt), затем измените хэш пароля на

PBKDF2( MD5( password ) )

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

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

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

И пока вы на нем, добавьте также поле версии для паролей.

EDIT. Криптография StackExchange имеет интересную дискуссию по этому методу.

Ответ 3

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

Ответ 4

Один из способов сделать это:

  • Введите новое поле для нового пароля
  • Когда пользователь регистрируется при проверке пароля на старый хэш
  • Если все в порядке, введите хэш в текстовый пароль с новым хешем
  • Удалить старый хэш

Затем постепенно у вас будут только пароли с новым хэшем

Ответ 5

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

Вы можете попробовать следующее:

Сначала добавьте новый столбец в таблицу ваших членов или в какой-либо таблице хранятся пароли.

ALTER TABLE members ADD is_pass_upgraded tinyint(1) default 0;

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

<?php
$username = $_POST['username'];
$password = $_POST['password'];

$auth_success = authenticateUser($username, $password); 
if (!$auth_success) {
    /**
     * They entered the wrong username/password. Redirect them back
     * to  the login page.
     */
} else {
    /**
     * Check to see if the member password has been upgraded yet
     */
    $username = mysql_real_escape_string($username);
    $sql = "SELECT id FROM members WHERE username = '$username' AND is_pass_upgraded = 0 LIMIT 1";
    $results = mysql_query($sql);

    /**
     * Getting any results from the query means their password hasn't been
     * upgraded yet. We will upgrade it now.
     */
    if (mysql_num_rows($results) > 0) {
        /**
         * Generate a new password hash using your new algorithm. That's
         * what the generateNewPasswordHash() function does.
         */
        $password = generateNewPasswordHash($password);
        $password = mysql_real_escape_string($password);

        /**
         * Now that we have a new password hash, we'll update the member table
         * with the new password hash, and change the is_pass_upgraded flag.
         */
        $sql = "UPDATE members SET password = '$password', is_pass_upgraded = 1 WHERE username = '$username' LIMIT 1";
        mysql_query($sql);
    }
}

Ваша функция authenticateUser() должна быть изменена на нечто похожее на это:

<?php
function authenticateUser($username, $password)
{
    $username = mysql_real_escape_string($username);

    /**
     * We need password hashes using your old system (md5 for example)
     * and your new system.
     */
    $old_password_hashed = md5($password);
    $new_password_hashed = generateBetterPasswordHash($password);
    $old_password_hashed = mysql_real_escape_string($old_password_hashed);
    $new_password_hashed = mysql_real_escape_string($new_password_hashed);

    $sql = "SELECT *
        FROM members
        WHERE username = '$username'
        AND
        (
            (is_pass_upgraded = 0 AND password = '$old_password_hashed')
            OR
            (is_pass_upgraded = 1 AND password = '$new_password_hashed')
        )
        LIMIT 1";
    $results = mysql_query($sql);
    if (mysql_num_rows($results) > 0) {
        $row = mysql_fetch_assoc($results);
        startUserSession($row);
        return true;
    } else {
        return false;
    }
}

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

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

Ответ 6

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