Как узнать, какие значения хороши для memory_cost, threads и time_cost для Argon2i в Symfony 4? - PullRequest
0 голосов
/ 28 сентября 2018

Я хочу использовать Argon2i для моего кодера Symfony 4, так как я видел несколько статей о том, как он, возможно, лучше, чем bcrypt или pbkdf2.К сожалению, я не знаю, какие значения использовать для memory_cost, time_cost или потоков в моей системе.Что такое хорошие ценности и как я могу определить, какими должны быть мои ценности?

1 Ответ

0 голосов
/ 28 сентября 2018

Что такое хорошие значения?

Это очень субъективно в зависимости от вашего сервера.@Martin достаточно хорошо описал это здесь , и вы можете прочитать спецификации RFC здесь .Но если подвести итог (и, возможно, поделиться своим личным мнением / лучшим ответом, основываясь только на десятках статей, которые я прочитал), то «хорошими» значениями являются:

  • Хэшвремя. Заставьте хеш занять от 0,5 мс до 500 мс в обычной системе (более высокие значения обеспечивают большую безопасность, но меньше опыта пользователя) или 1 с + в системе с высокой степенью защиты.Опять же, даже эти цифры являются весьма субъективными, и это просто общий консенсус, основанный на том, что я прочитал.Причина, по которой вы хотите, чтобы хеш занимал так много времени, заключается в том, что когда хакер пытается взломать хеш, это займет столько времени на каждую попытку хэширования.Обычные попытки взлома могут произойти за несколько миллисекунд, поэтому растягивание его, так что это займет больше времени, в основном заставит взломать хэш навсегда, и поэтому хакер (надеюсь?) Сдастся.

  • Память. У больших серверов будет больше оперативной памяти.Лично в это время я бы сказал, что 128MB на сервере с довольно большим объемом оперативной памяти и хорошим процессором, вероятно, был бы тем максимумом, который вы хотели бы использовать (на момент написания этой статьи), но это только мое мнение.Это значение действительно во многом зависит от того, какова оперативная память вашего веб-сервера, в первую очередь - вы не хотите использовать большие значения на серверах, которые уже потребляют ОЗУ.Значение по умолчанию для Argon2 составляет 1 МБ.При этом по умолчанию используются следующие значения времени:

    • Сервер Common Cloud 512 МБ, 1 ядро: 3-5 мс
    • Сервер Common Cloud 2 ГБ, 2 ядра, 1-3 мс
    • 512 МБ Raspberry Pi Zero: 75-85мс
  • Потоки. В основном, сколько потоков ЦП будет занимать.Как и memory_cost, этот вид вращается вокруг использования процессора вашим сервером.В моем опыте я взял максимальное количество ядер и разделил его пополам, и это, как правило, хорошее число (если не сказать больше, для начала), но вам нужно поэкспериментировать, чтобы увидеть.

  • Стоимость времени. Это значение должно быть вычислено последним.Начните с 1, найдите нужные значения для memory_cost и потоков, а затем увеличьте это значение.В моем опыте, если вы получаете memory_cost и нить прямо это число не получают больше, чем 5, но опять-таки это ДАЛЕКО спорно.

Это все сказанные (и цель этого поставо-первых) тест, приведенный ниже, является попыткой помочь вам найти значения, которые будут работать для системы YOUR .Обратите внимание, что если вы когда-либо меняете свое оборудование / ОС / службу веб-сервера / некоторые существенные изменения на вашем сервере, вы должны ВСЕГДА повторить эти вычисления.Также не запускайте это на своем сервере разработки, устанавливайте значения и думайте, что они будут одинаковыми на вашем рабочем сервере - вы должны делать это на каждом сервере, на котором вы собираетесь использовать код.

Test:

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

Twig:

<form action="{{ path('test') }}" method="post">
    <p>
        <label for="time_cost">Time Cost:</label>
        <input type="text" id="time_cost" name="time_cost" value="{{ last_time_cost }}" />
    </p>
    <p>
        <label for="memory_cost">Memory Cost:</label>
        <input type="text" id="memory_cost" name="memory_cost" value="{{ last_memory_cost }}" />
    </p>
    <p>
        <label for="thread_cost">Thread Cost:</label>
        <input type="text" id="thread_cost" name="thread_cost" value="{{ last_thread_cost }}" />
    </p>
    <p>
        <label for="iterations">Iterations (how many times to compute the hash):</label>
        <input type="text" id="iterations" name="iterations" value="{{ last_iteration }}" />
    </p>
    <p>
        <label for="desired_time">Desired Time in seconds. Normal system: 0.5, High security: 1 (or higher).:</label>
        <input type="text" id="desired_time" name="desired_time" value="{{ last_desired_time }}" />
    </p>
    <p>
        <label for="password">Password to hash:</label>
        <input type="text" id="password" name="password" value="{{ last_password }}" />
    </p>
    <button type="submit">Run Test</button>

    <div>Average seconds taken (over {{ last_iteration }} iterations): {{ total }}</div>
    <div>Ideal seconds taken: {{ last_desired_time }}</div>
    <div>Difference: <span style="color:{{ style }}">{{ diff }}</span></div>
</form>

Контроллер:

/**
 ** @Route("/test", name="test")
 */
public function test(Request $request)
{
    $time_cost = $request->request->get('time_cost');
    $memory_cost = $request->request->get('memory_cost');
    $thread_cost = $request->request->get('thread_cost');
    $desiredTime = $request->request->get('desired_time');
    $iterations = $request->request->get('iterations');
    $password = $request->request->get('password');

    if (empty($memory_cost) || !is_numeric($memory_cost))
        $memory_cost = 16384;

    if (empty($time_cost) || !is_numeric($time_cost))
        $time_cost = 2;

    if (empty($thread_cost) || !is_numeric($thread_cost))
        $thread_cost = 4;

    echo $desiredTime;

    if (empty($desiredTime) || (!is_numeric($desiredTime) &&!is_float($desiredTime)))
        $desiredTime = 0.25;

    if (empty($iterations) || !is_numeric($iterations))
        $iterations = 10;

    if (empty($password))
        $password = 'correct horse battery staple';

    $options = [
        'memory_cost' => $memory_cost,
        'time_cost' => $time_cost,
        'threads' => $thread_cost
    ];

    $totalTime = 0;
    for($i = 1; $i <= $iterations; $i++)
    {
        $start = microtime(true);
        password_hash($password, PASSWORD_ARGON2I, $options);
        $end = microtime(true);
        $total = $end - $start;
        $totalTime = $totalTime + $total;
    }

    $diff = $desiredTime - $totalTime / $iterations;

    if ($diff > 0 || $diff < -0.50)
        $style = 'red';
    else
        $style = 'green';

    return $this->render('index/test.html.twig', array(
        'last_thread_cost' => $thread_cost,
        'last_time_cost' => $time_cost,
        'last_memory_cost' => $memory_cost,
        'last_iteration' => $iterations,
        'last_desired_time' => $desiredTime,
        'last_password' => $password,
        'total' => $totalTime / $iterations,
        'diff' => $diff,
        'style' => $style,
    ));
}

Получив значения, подходящие для вашей среды, вы можете установить их для своего кодировщика в security.yaml

security.yaml /app/config/packages/security.yaml

Примечание. Здесь приведены примеры значений.НЕ используйте их (без тестирования), используйте выше, чтобы найти ВАШИ значения.

security:
    ...
    encoders:
        App\Security\SecurityUser:
            algorithm: argon2i
            memory_cost: 102400
            time_cost: 3
            threads: 4
...