Хранение паролей PHP с HMAC + nonce - важна ли случайность nonce? - PullRequest
6 голосов
/ 08 января 2011

Несколько лет я спрашивал здесь на stackoverflow о том, как сделать безопасное хранение паролей PHP. основной ответ предлагает использовать следующий алгоритм хеширования:

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

В ответе предлагается использовать random nonce.Есть ли какое-либо преимущество в наличии случайного одноразового номера по сравнению с простыми уникальными одноразовыми номерами?

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

Теперь каждый пользователь может выбрать имя пользователя.У каждого пользователя есть свое имя, которое не меняется, и два разных пользователя не могут иметь одно и то же имя.Имена пользователей все еще не случайны, но они также не являются последовательными.Будут ли имена пользователей достаточно хорошими как одноразовые?Было бы лучше, чем использовать идентификатор пользователя?

Ответы [ 3 ]

2 голосов
/ 13 января 2011

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

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

function pbkdf2($password,$salt,$iter_count = 1500,$key_length = 32,$algorithm = 'sha512') 
{
    /*
      @param string password -- password to be encrypted
      @param string salt -- salt to encrypt with
      @param int iter_count -- number of times to iterate blocks
      @param key_length -- length of key to return
      @param $algorithm -- algorithm to use in hashing

      @return string key
    */

    //determine the length of the hahs
    $hash_length = strlen(hash($algorithm,NULL,TRUE));
    //determine the number of key blocks to compute
    $key_blocks = ceil($key_length/$hash_length);
    //initialize key
    $key = '';

    //create the key itself
    //create blocks
    for($block_count = 1;$block_count <= $key_blocks;$block_count++)
    {
        //initalize hash for this block
        $iterated_block = $block = hash_hmac($algorithm,$salt.pack('N',$block_count),$password,TRUE);
        //iterate blocks
        for($iterate = 1;$iterate <= $iter_count;$iterate++)
        {
            //xor each iterate
            $iterated_block ^= ($block = hash_hmac($algorithm,$block,$password,TRUE));
        }
        //append iterated block
        $key .= $iterated_block;
    }
    //return the key
    return substr($key,0,$key_length);
}
  1. Первое, что он делает, это вычисляет длину хэша.
  2. Затем он определяет, сколько ключевых блоковтребуются для указанной длины ключа
  3. Затем инициализируется хэш (ключ) для возврата
  4. устанавливает цикл for, который будет создавать каждый блок
  5. принимает начальный хешблок со счетчиком блоков в двоичном коде, добавленный к соли
  6. начинает цикл для итерации блока $ iter_count times (создайте свой хеш)
  7. XOR каждая итерация и добавьте его в $ iterated_block(xor предыдущего хэша к текущему)
  8. Завершение цикла XOR
  9. добавление $ iterated_block к $ key для каждого блока
  10. завершение цикла блока
  11. возвращение ключа

Мне кажется, это, наверное, лучший способ сделать это.Может я слишком параноик?

2 голосов
/ 08 января 2011

ЭТО ВСЕ НА ПРЕДПОСЫЛКЕ, ЧТО НЕ СОДЕРЖИТСЯ СОЛЬ ...

Если под nonce вы подразумеваете соль, то да, что требует создания дополнительных радужных таблиц.Обычно достаточно соли более 20 символов, но для экстремальных условий безопасности вам понадобится новая случайная соль для каждого пароля.

Также хороший выбор в медленном хэше http://www.php.net/manual/en/function.hash.php#89574, без сарказма.Но мне нравится Pinemd.

Не видел нижнюю половину вашего ответа.Для уточнения: одноразовые номера используются для предотвращения использования радужных таблиц.Будут ли идентификаторы работать, зависит только от длины идентификаторов.Случайность не технически важна, она просто требует большего количества радужных таблиц.Например, допустим, вы использовали символ «a» в качестве одноразового номера, а пароль был длиной 2 символа, необходимо было создать радужную таблицу a-aa, a-ab a-ac и так далее.Если вы используете случайную единицу каждый раз, возможно, вам придется сделать все перестановки «а» + все перестановки других случайных символов.

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

0 голосов
/ 09 января 2011

Для хранения пароля достаточно использовать:

sha512(salt + password)

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

Положение соли перед паролем поможет скрыть шаблоны хэша, если у некоторых пользователей будет один и тот же пароль.1013 *

Nonce не требуется, поскольку он предназначен для предотвращения ответной атаки.Эта защита невозможна в вашей архитектуре.

Использование HMAC для предотвращения коллизий бесполезно, потому что a) мы используем хэш не для MAC, b) чтобы сделать вероятность коллизии 50% для SHA-512 вам нужно вычислить около 2 ^ 256 значений.И 2 ^ 256 - это действительно астрономическое число.

...